From: Steve Sutton
Date: Tue, 4 Nov 2014 18:21:27 +0000 (-0500)
Subject: convert to git
X-Git-Url: http://cvs2.gaslightmedia.com/gitweb/?a=commitdiff_plain;h=refs%2Fheads%2Fmaster;p=web%2Fwww.gaslightmedia.com.git
convert to git
---
f45cecd35d812728e2e4970645c3edff448bdfe2
diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 0000000..027f934
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,2 @@
+uploads uploads.tar
+
diff --git a/.htaccess b/.htaccess
new file mode 100644
index 0000000..d03dc14
--- /dev/null
+++ b/.htaccess
@@ -0,0 +1,57 @@
+
+Order allow,deny
+Deny from all
+
+
+Order allow,deny
+Deny from all
+
+
+Order allow,deny
+Deny from all
+
+#Options -MultiViews
+#ErrorDocument 404 /404.html
+RewriteEngine On
+AddDefaultCharset utf-8
+#RewriteBase /www.gaslightmedia.com/
+##RewriteCond %{HTTP_HOST} !^(.*)\.gaslightmedia\.com$ [NC]
+##RewriteRule ^(.*)$ http://www.gaslightmedia.com.com/$1 [R=301,L]
+RewriteCond %{HTTP_HOST} !^(.*)\.gaslightmedia\.com$ [NC]
+RewriteRule ^(.*)$ http://www.gaslightmedia.com/$1 [R=301,L]
+
+Redirect 301 /connectivity/dsl_wireless_service_agreement.html http://www.gaslightmedia.com/dslwireless-service-agreement-121/
+# Press
+RewriteRule press-archives/$ index.php?catid=3&archive=1 [L]
+RewriteRule press/([0-9]*)/$ index.php?catid=3&press_id=$1 [L]
+
+# isp recent connected
+RewriteRule ^isp-portfolio-detail-([0-9]*)/([0-9]*)/$ index.php?catid=$1&pcatid=$1&busid=$2 [L]
+RewriteRule ^isp/.*-([0-9]*)/$ index.php?catid=$1 [L]
+RewriteRule ^isp/.*-([0-9]*)/([0-9]*)/$ index.php?catid=$1&pcatid=$2 [L]
+
+# web portfolio
+RewriteRule ^portfolio-category/.*-([0-9]*)/$ index.php?catid=100&pcatid=$1 [L]
+RewriteRule ^portfolio-detail-([0-9]*)/([0-9]*)/$ index.php?catid=100&pcatid=$1&busid=$2 [L]
+RewriteRule ^web/.*-([0-9]*)/$ index.php?catid=$1 [L]
+RewriteRule ^web/.*-([0-9]*)/([0-9]*)/$ index.php?catid=$1&pcatid=$2 [L]
+RewriteRule ^web/.*-([0-9]*)/([0-9]*)/([0-9]*)/$ index.php?catid=$1&pcatid=$2&id=$3 [L]
+
+# rewrites for the toolbox pages
+RewriteRule ^.*-([0-9]*)/index.php index\.php?%{QUERY_STRING}
+RewriteRule ^.*-([0-9]*)/$ index\.php?catid=$1 [L]
+
+#RewriteRule site-map index.php?catid=1&sitemap=1
+AddType application/x-httpd-php .tpl
+
+# short urls
+RewriteCond %{REQUEST_URI} !(^.*-([0-9]*)/$)
+RewriteCond %{REQUEST_URI} !(^support|^mac|^pc|^join|^meeting)
+RewriteRule ^([A-Za-z0-9_-]*)/$ index.php?glmPage=$1 [L]
+
+# Redirects
+RewriteRule ^jobs http://www.gaslightmedia.com/job-openings-131/
+RewriteRule ^jobs/ http://www.gaslightmedia.com/job-openings-131/
+RewriteRule ^billpay https://ws3.gaslightmedia.com/www/index.php?catid=117
+RewriteRule ^wsa http://www.gaslightmedia.com/wireless-service-agreement-136/
+RewriteRule ^responsivedesign http://www.gaslightmedia.com/portfolio-category/Responsive-Design--82/
diff --git a/.htaccess-old b/.htaccess-old
new file mode 100644
index 0000000..07c1afd
--- /dev/null
+++ b/.htaccess-old
@@ -0,0 +1,55 @@
+
+Order allow,deny
+Deny from all
+
+
+Order allow,deny
+Deny from all
+
+
+Order allow,deny
+Deny from all
+
+#Options -MultiViews
+#ErrorDocument 404 /404.html
+RewriteEngine On
+AddDefaultCharset utf-8
+#RewriteBase /www.gaslightmedia.com/
+RewriteCond %{HTTP_HOST} !^(.*)\.gaslightmedia\.com$ [NC]
+RewriteRule ^(.*)$ http://www.gaslightmedia.com.com/$1 [R=301,L]
+
+Redirect 301 /connectivity/dsl_wireless_service_agreement.html http://www.gaslightmedia.com/dslwireless-service-agreement-121/
+# Press
+RewriteRule press-archives/$ index.php?catid=3&archive=1 [L]
+RewriteRule press/([0-9]*)/$ index.php?catid=3&press_id=$1 [L]
+
+# isp recent connected
+RewriteRule ^isp-portfolio-detail-([0-9]*)/([0-9]*)/$ index.php?catid=$1&pcatid=$1&busid=$2 [L]
+RewriteRule ^isp/.*-([0-9]*)/$ index.php?catid=$1 [L]
+RewriteRule ^isp/.*-([0-9]*)/([0-9]*)/$ index.php?catid=$1&pcatid=$2 [L]
+
+# web portfolio
+RewriteRule ^portfolio-category/.*-([0-9]*)/$ index.php?catid=100&pcatid=$1 [L]
+RewriteRule ^portfolio-detail-([0-9]*)/([0-9]*)/$ index.php?catid=100&pcatid=$1&busid=$2 [L]
+RewriteRule ^web/.*-([0-9]*)/$ index.php?catid=$1 [L]
+RewriteRule ^web/.*-([0-9]*)/([0-9]*)/$ index.php?catid=$1&pcatid=$2 [L]
+RewriteRule ^web/.*-([0-9]*)/([0-9]*)/([0-9]*)/$ index.php?catid=$1&pcatid=$2&id=$3 [L]
+
+# rewrites for the toolbox pages
+RewriteRule ^.*-([0-9]*)/index.php index\.php?%{QUERY_STRING}
+RewriteRule ^.*-([0-9]*)/$ index\.php?catid=$1 [L]
+
+#RewriteRule site-map index.php?catid=1&sitemap=1
+AddType application/x-httpd-php .tpl
+
+# short urls
+RewriteCond %{REQUEST_URI} !(^.*-([0-9]*)/$)
+RewriteCond %{REQUEST_URI} !(^support|^mac|^pc|^join|^meeting)
+RewriteRule ^([A-Za-z0-9_-]*)/$ index.php?glmPage=$1 [L]
+
+# Redirects
+RewriteRule ^jobs http://www.gaslightmedia.com/job-openings-131/
+RewriteRule ^jobs/ http://www.gaslightmedia.com/job-openings-131/
+RewriteRule ^billpay https://ws3.gaslightmedia.com/www/index.php?catid=117
+RewriteRule ^wsa http://www.gaslightmedia.com/wireless-service-agreement-136/
+RewriteRule ^responsivedesign http://www.gaslightmedia.com/portfolio-category/Responsive-Design--82/
diff --git a/GLM_site_check.phtml b/GLM_site_check.phtml
new file mode 100644
index 0000000..91236ba
--- /dev/null
+++ b/GLM_site_check.phtml
@@ -0,0 +1,12 @@
+
diff --git a/Toolkit/.htaccess b/Toolkit/.htaccess
new file mode 100644
index 0000000..532b751
--- /dev/null
+++ b/Toolkit/.htaccess
@@ -0,0 +1,2 @@
+#IndexIgnore */*
+#Options All -Indexes
diff --git a/Toolkit/Banners.php b/Toolkit/Banners.php
new file mode 100644
index 0000000..6ce0bfc
--- /dev/null
+++ b/Toolkit/Banners.php
@@ -0,0 +1,392 @@
+
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: Banners.php,v 1.1.1.1 2009/09/17 20:08:55 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Create, process and display banners
+ *
+ * @category Banners
+ * @package Toolkit_Banners
+ * @author Jamie Kahgee
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Banners
+{
+ // {{{ properties
+
+ /**
+ * Holds the subnav li links
+ *
+ * @var string
+ * @access protected
+ */
+ protected $nav;
+
+ /**
+ * Holds the sub-navigation array
+ *
+ * @var array
+ * @access protected
+ */
+ protected $navConfig = array();
+
+ /**
+ * Whether bottom banners should be turned on or off
+ *
+ * @var Const
+ * @access Public
+ */
+ const BOTTOM_BANNERS = true;
+
+ /**
+ * Whether side banners should be turned on or off
+ *
+ * @var Const
+ * @access Public
+ */
+ const SIDE_BANNERS = false;
+
+ /**
+ * Whether this client has a memberdb or not
+ *
+ * This directly effects how the create/edit forms for the banner render
+ * as well as how the banners are displayed on the front end. When this is
+ * is turned on, extra select elements appear on the create/edit forms
+ * that allow a user to associate a banner w/ member categories. And
+ * on the front end, banners associated w/ categories will show up on
+ * the pages.
+ *
+ * FYI: A banner can be associated w/ a member category BUT NOT a
+ * toolbox navigational page and still show on that page IFF the member
+ * member category was assigned to that page.
+ *
+ * @var Const
+ * @access Public
+ */
+ const HAS_MEMBER_DB = true;
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Class constructor
+ *
+ * @param PDO $pdo PHP Data Object to use for DB
+ *
+ * @return void
+ * @access public
+ */
+ public function __construct(PDO $pdo)
+ {
+ $this->dbh = $pdo;
+ if (!empty($_GET['type'])) {
+ $this->setupDefines();
+ }
+ }
+
+ // }}}
+
+ // {{{ createNav()
+
+ /**
+ * Creates the subnav links for the admin
+ *
+ * @return void
+ *
+ * @author Jamie Kahgee
+ * @access Public
+ */
+ public function createNav()
+ {
+ $subnav = array(
+ 'List Banners' => 'banners.php?action=listBanners',
+ );
+
+ if (self::BOTTOM_BANNERS) {
+ $subnav['Create Bottom Banner']
+ = 'banners.php?type=bottom&action=editBottomBanner';
+ }
+ if (self::SIDE_BANNERS) {
+ $subnav['Create Side Banner']
+ = 'banners.php?type=side&action=editSideBanner';
+ }
+
+ $this->navConfig = $subnav;
+ if (!is_array($this->navConfig)) {
+ $this->navConfig = (array)$this->navConfig;
+ }
+ if (array_walk($this->navConfig, array($this, 'makeLiLinks'))) {
+ echo '
'.$this->nav.'
';
+ }
+ }
+
+ // }}}
+
+ // {{{ &factory()
+
+ /**
+ * Provides an interface for generating Banner:: objects of various types
+ *
+ * @param String $driver The kind of Banner:: object to instantiate.
+ *
+ * @return Object Banner an instance of the driver class or if fails
+ * a PEAR error.
+ *
+ * @author Jamie Kahgee
+ * @access Public
+ */
+ public function &factory($driver)
+ {
+ $class = "Toolkit_Banners_$driver";
+ $file = BASE . str_replace('_', '/', $class) . '.php';
+ // The class for the driver should reside in this file
+ // if it doesn't, we have an error.
+ if (file_exists($file)) {
+ // The file exists, now make sure the class exists,
+ // class_exists calls __autoload by default, so it should
+ // automatically load the file when testing for its existance
+ if (class_exists($class)) {
+ // Get all function arguments passed in.
+ $params = func_get_args();
+ // remove the first argument, driver name, and convert
+ // to a string delimited by commas so we can pass off
+ // to class constructor call.
+ $args = implode(', ', (array_splice($params, 1)));
+
+ $instantiatedClass =& new $class($$args);
+ return $instantiatedClass;
+ } else {
+ return PEAR::raiseError("Class $driver does not exist in $file");
+ }
+ } else {
+ return PEAR::raiseError("Unable to find class for driver $driver");
+ }
+ }
+
+ // }}}
+
+ // {{{ makeLiLinks()
+
+ /**
+ * Assists the createNav function for creating the subnav in admin
+ *
+ * @param string $link the url to the page
+ * @param string $name name of the link
+ *
+ * @return void
+ *
+ * @author Jamie Kahgee
+ * @access Protected
+ * @see Toolkit_Banners::createNav()
+ */
+ protected function makeLiLinks($link, $name)
+ {
+ $url = parse_url($link);
+ $action = end(explode('=', $url['query']));
+ if ($_GET['action'] == $action) {
+ $attr = ' id="current"';
+ }
+ $this->nav .= '
Below is the list of businesses you have added to your Trip Planner. The form below will be sent to each individual business listing that has an email address listed with their business listing. For those businesses with no email address, we have included their phone numbers for you to call directly and request additional information.
+
Request Information by Phone from:
+
These business listings have no current email address on file. To receive additional information please call the phone numbers listed next to each business name.
Thank you for your interest in {client_info[name]:h}'!
+
Sincerely,
+
{client_info[name]:h}
+
{client_info[url]:h}
+
+
+
diff --git a/Toolkit/DataGridBuilder.php b/Toolkit/DataGridBuilder.php
new file mode 100644
index 0000000..691d539
--- /dev/null
+++ b/Toolkit/DataGridBuilder.php
@@ -0,0 +1,285 @@
+
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Create Datagrids for displaying data
+ *
+ * This abstract class handles all the base functionality of creating
+ * handeling all the details associated w/ a regular dataGrid.
+ * 1. Creation
+ * 2. Sorting (via column headers or sortform)
+ * 3. Pagenation
+ *
+ * @category Structures
+ * @package Toolkit_DataGridBuilder
+ * @author Jamie Kahgee
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @Release CVS: $Id: DataGridBuilder.php,v 1.1.1.1 2009/09/17 20:08:55 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit_SortForm, Structures_DataGrid
+ */
+abstract class Toolkit_DataGridBuilder extends Structures_DataGrid
+{
+ // {{{ properties
+
+ /**
+ * Options to pass to DataGrid
+ *
+ * @var array
+ * @access protected
+ */
+ protected $options;
+
+ /**
+ * Rendering options for DataGrid
+ *
+ * @var array
+ * @access protected
+ */
+ protected $rendererOptions = array(
+ 'sortIconASC' => '⇑',
+ 'sortIconDESC' => '⇓',
+ 'evenRowAttributes' => 'class="even"',
+ 'oddRowAttributes' => 'class="odd"',
+ 'sortingResetsPaging' => false,
+ );
+
+ /**
+ * Rendering options for DataGrid paging element
+ *
+ * @var array
+ * @access protected
+ */
+ protected $pagerOptions = array(
+ 'nextImg' => 'Next',
+ 'prevImg' => 'Previous',
+ 'separator' => '',
+ 'spacesBeforeSeparator' => 0,
+ 'spacesAfterSeparator' => 0,
+ 'containerClass' => 'paging',
+ );
+
+ /**
+ * SQL query used to obtain the DataGrid
+ *
+ * @var unknown
+ * @access protected
+ */
+ protected $sql;
+
+ /**
+ * How many records must exist in the Datagrid before the sort form shows up
+ *
+ * @var integer
+ * @access protected
+ */
+ protected $sortableAfter = 10;
+
+ /**
+ * The HTML table id of the DataGrid
+ *
+ * @var string
+ * @access protected
+ */
+ protected $tableId = 'dataGrid';
+
+ /**
+ * The HTML class name of the DataGrid
+ *
+ * @var string
+ * @access protected
+ */
+ protected $tableClass = 'dataGrid';
+
+ /**
+ * The HTML id of the DataGrid sorting form (when present)
+ *
+ * @var string
+ * @access protected
+ */
+ protected $sortFormId = 'gridSorter';
+
+ /**
+ * Message to display to users if no records were found
+ *
+ * @var String
+ * @access Protected
+ * @see Toolkit_DataGridBuilder::setNoRecordMessage()
+ */
+ protected $noRecMessage = 'No Records';
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * DataGrid constructor
+ *
+ * Instantiates a DataGrid and sets up when to make the grid sortable
+ *
+ * @param PDO $pdo PDO object used in the datagrid
+ * @param integer $limit The number of records to display per page.
+ * @param integer $page The current page view. In most cases,
+ * this is useless. Note: if you specify
+ * this, the "page"GET variable will be ignored.
+ * @param string $rendererType The type of renderer to use. You may
+ * prefer to use the $type argument of
+ * render, fill or getOutput.
+ *
+ * @return void
+ * @access public
+ */
+ public function __construct(
+ PDO $pdo,
+ $limit = null,
+ $page = null,
+ $rendererType = null
+ ) {
+ parent::__construct($limit, $page, $rendererType);
+
+ $this->options = array('dbc' => $pdo);
+ if (!is_null($limit)) {
+ $this->sortableAfter = $limit;
+ }
+ }
+
+ // }}}
+
+ // {{{ configureColumns()
+
+ /**
+ * configure retrieved columns
+ *
+ * Tells the DataGrid how to render the retrieved columns
+ *
+ * @return void
+ * @access protected
+ */
+ abstract protected function configureColumns();
+
+ // }}}
+
+ // {{{ setNoRecordMessage()
+
+ /**
+ * The message to display if no results were found from the sql query
+ *
+ * @param string $msg No result message.
+ *
+ * @return void
+ * @access public
+ */
+ public function setNoRecordMessage($msg)
+ {
+ $this->noRecMessage = $msg;
+ }
+
+ // }}}
+ // {{{ setQuery()
+
+ /**
+ * Sets the sql query to use in the DataGrid to get the results
+ *
+ * @param string $sql The SQL query
+ *
+ * @return void
+ * @access public
+ */
+ public function setQuery($sql)
+ {
+ $this->sql = $sql;
+ }
+
+ // }}}
+ // {{{ show()
+
+ /**
+ * Displays the DataGrid results
+ *
+ * @return void
+ * @access public
+ */
+ public function show()
+ {
+ echo $this->toHTML();
+ }
+
+ // }}}
+
+ // {{{ toHTML()
+
+ /**
+ * returns a HTML table of the datagrid
+ *
+ * @return string
+ * @access public
+ */
+ public function toHTML()
+ {
+ $this->configureColumns();
+
+ try {
+ $bind = $this->bind($this->sql, $this->options, 'PDO');
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+
+ if (PEAR::isError($bind)) {
+ return Toolkit_Common::handleError($bind);
+ } elseif (($recCount = $this->getRecordCount()) > 0) {
+ $this->setRendererOptions($this->rendererOptions);
+ $renderer =& $this->getRenderer();
+ // Allows us to turn off the id name for the table,
+ // when we subclass this class out.
+ if ($this->tableId) {
+ $renderer->setTableAttribute('id', $this->tableId);
+ }
+ // Allows us to turn off the class name for the table,
+ // when we subclass this class out.
+ if ($this->tableClass) {
+ $renderer->setTableAttribute('class', $this->tableClass);
+ }
+ $gridBody = $this->getOutput();
+
+ if (PEAR::isError($gridBody)) {
+ return Toolkit_Common::handleError($gridBody);
+ }
+
+ $gridPager = $this->getOutput(
+ DATAGRID_RENDER_PAGER,
+ array('pagerOptions' => $this->pagerOptions)
+ );
+ if (PEAR::isError($gridPager)) {
+ return Toolkit_Common::handleError($gridPager);
+ }
+
+ if ($recCount > $this->sortableAfter) {
+ $form = new Toolkit_SortForm($this->sortFormId);
+ $options = array('directionStyle' => 'radio');
+ $this->fill($form, $options, DATAGRID_RENDER_SORTFORM);
+ // Datagrid never ads a submit button.
+ $form->addElement('submit', null, 'Submit');
+ $gridSorter = $form->toHTML();
+ }
+
+ return $gridPager . $gridSorter . $gridBody . $gridPager;
+ } else {
+ return "
{$this->noRecMessage}
";
+ }
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Database.php b/Toolkit/Database.php
new file mode 100644
index 0000000..e5229ad
--- /dev/null
+++ b/Toolkit/Database.php
@@ -0,0 +1,123 @@
+
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: Database.php,v 1.1 2009/12/15 20:18:15 jamie Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Database Singleton class
+ *
+ * @category Database
+ * @package Toolkit_Database
+ * @author Jamie Kahgee
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Database
+{
+ // {{{ properties
+
+ /**
+ * Database handler object
+ *
+ * @var PDO
+ * @access private
+ */
+ private $_dbh;
+
+ /**
+ * Class instance
+ *
+ * @var Toolkit_Database
+ * @access private
+ */
+ private static $_instance;
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Class constructor
+ *
+ * Make the database handler connection for the class
+ *
+ * @access private
+ */
+ private function __construct()
+ {
+ try {
+ $dsn = 'pgsql:' . CONN_STR;
+ // Keep the fetch mode set to FETCH_BOTH, we use
+ // associative arrays throughout our apps, but some PEAR lib
+ // apps require numerical indicies to work correctly.
+ // i.e. (DataGrids working w/ PDO's)
+ $driverOptions = array(
+ PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_BOTH,
+ );
+ $this->_dbh = new PDO($dsn, null, null, $driverOptions);
+ $this->_dbh->setAttribute(
+ PDO::ATTR_ERRMODE,
+ PDO::ERRMODE_EXCEPTION
+ );
+ $this->_dbh->query("SET DATESTYLE TO 'SQL,US'");
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ __clone()
+
+ /**
+ * Clone magic method
+ *
+ * Don't allow cloning of instances of this class
+ * which could potentially duplicate system resources
+ * and make extra DB connections
+ *
+ * @return void
+ * @access private
+ */
+ private function __clone()
+ {
+ // Do nothing so we don't create duplicate resources
+ }
+
+ // }}}
+
+ // {{{ getInstance()
+
+ /**
+ * Get an instance of this class
+ *
+ * If this object hasn't been instantiated once already
+ * then create the object and return the dbh.
+ * Otherwise just return the already instantiated dbh.
+ *
+ * @return PDO $_instance database handler instance
+ * @access public
+ * @static
+ */
+ public static function getInstance()
+ {
+ if (!(self::$_instance instanceof self)) {
+ self::$_instance = new self();
+ }
+
+ return self::$_instance->_dbh;
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Events/AddEventForm.php b/Toolkit/Events/AddEventForm.php
new file mode 100755
index 0000000..e6570b3
--- /dev/null
+++ b/Toolkit/Events/AddEventForm.php
@@ -0,0 +1,904 @@
+
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: AddEventForm.php,v 1.1.1.1 2009/09/17 20:08:57 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * New Event Form
+ *
+ * @category Events
+ * @package Toolkit_Events
+ * @author Jamie Kahgee
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Events_AddEventForm
+ extends Toolkit_FormBuilder implements Toolkit_Form
+{
+ // {{{ properties
+
+ /**
+ * Table in Database which holds the contact data
+ *
+ * @var string
+ * @access public
+ */
+ public $tableName = 'event';
+
+ /**
+ * 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 = '
+
+ 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;
+
+ // }}}
+ // {{{ __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
+ ) {
+ parent::__construct(
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+
+ $this->dbh = $pdo;
+
+ // Default Renderer Form templates for QuickForm in respect to this
+ // classes needs.
+ $this->template = dirname(__FILE__) . '/templates/currentTables/';
+ if ($this->email !== false && empty($this->email)) {
+ // Set to false to turn off email function.
+ $this->email = OWNER_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 = ($_SERVER['HTTPS'] == 'on') ?
+ BASE_SECURE_URL : 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)
+ {
+ $validate = false;
+ foreach ($date as $i) {
+ if (is_numeric($i)) {
+ $validate = true;
+ break;
+ }
+ }
+
+ if ($validate) {
+ // at least on date list had a number in it.
+ $d = implode('-', $date);
+ return Validate::date($d, array('format' =>'%n-%j-%Y'));
+ } else {
+ // no date numbers were selected
+ return true;
+ }
+ }
+
+ // }}}
+ // {{{ 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;
+ }
+
+ $t1 = mktime(0, 0, 0, $d[0]['m'], $d[0]['d'], $d[0]['Y']);
+ $bdate = new Date($t1);
+ $t2 = mktime(0, 0, 0, $d[1]['m'], $d[1]['d'], $d[1]['Y']);
+ $edate = new Date($t2);
+
+ // 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);
+ }
+
+ // }}}
+ // {{{ 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' => 'text',
+ 'req' => true,
+ 'name' => 'header',
+ 'display' => 'Event Name'
+ );
+ $e[] = array(
+ 'type' => 'date',
+ 'req' => true,
+ 'name' => 'bdate',
+ 'display' => 'Start Date',
+ 'opts' => array(
+ 'format' => 'm / d / Y',
+ 'minYear' => date('Y'),
+ 'maxYear' => date('Y') + 5,
+ 'addEmptyOption' => true,
+ 'emptyOptionValue' => '',
+ 'emptyOptionText' => array(
+ 'm' => 'mm',
+ 'd' => 'dd',
+ 'Y' => 'yyyy'
+ ),
+ ),
+ 'att' => array('class' =>'sdate'),
+ );
+ $e[] = array(
+ 'type' => 'date',
+ 'req' => false,
+ 'name' => 'edate',
+ 'display' => 'End Date',
+ 'opts' => array(
+ 'format' => 'm / d / Y',
+ 'minYear' => date('Y'),
+ 'maxYear' => date('Y') + 5,
+ 'addEmptyOption' => true,
+ 'emptyOptionValue' => '',
+ 'emptyOptionText' => array(
+ 'm' => 'mm',
+ 'd' => 'dd',
+ 'Y' => 'yyyy'
+ ),
+ ),
+ 'att' => array('id' =>'edate'),
+ );
+ $e[] = array(
+ 'type' => 'date',
+ 'req' => true,
+ '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' => 'topicid',
+ 'display' => 'Topic',
+ 'opts' => $this->getTopicFields(),
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'loc',
+ 'display' => 'Location'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'url',
+ 'display' => 'Website'
+ );
+ $e[] = array(
+ 'type' => 'textarea',
+ 'req' => false,
+ 'name' => 'descr',
+ 'display' => 'Description'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'contact',
+ 'display' => 'Contact Person'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'email',
+ 'display' => 'Contact Email'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'phone',
+ 'display' => 'Contact Phone'
+ );
+ 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'
+ );
+
+ $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 Topic!',
+ '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('bdate', 'edate'),
+ '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' => 'bdate',
+ 'message' => 'ERROR: Invalid date!',
+ 'type' => 'callback',
+ 'format' => array(&$this, 'checkDate'),
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => 'edate',
+ 'message' => 'ERROR: Invalid date!',
+ 'type' => 'callback',
+ 'format' => array(&$this, 'checkDate'),
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => 'url',
+ 'message' => 'ERROR: Please include full address! ('.BASE_URL.')',
+ 'type' => 'checkURI',
+ 'format' => array(
+ 'allowed_schemes' => array('http', 'https'),
+ 'strict' => true
+ ),
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => '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()
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM topic
+ ORDER BY descr";
+
+ $topics = array('' => '-- Select --');
+ foreach ($this->dbh->query($sql) as $row) {
+ $topics[$row['id']] = $row['descr'];
+ }
+
+ return $topics;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ 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(array $d)
+ {
+ return checkdate((int) $d['m'], (int) $d['d'], (int) $d['Y']);
+ }
+
+ // }}}
+
+ // {{{ 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'));
+
+ // 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['btime']['element'] = $foo;
+ }
+
+ try {
+ $sql = "
+ SELECT descr
+ FROM topic
+ WHERE id = :id";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(
+ ':id',
+ $this->formData['topicid']['element'],
+ PDO::PARAM_INT
+ );
+ $stmt->execute();
+ $stmt->bindColumn('descr', $this->formData['topicid']['element']);
+ $stmt->fetch();
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+
+ $page->email_from = FROM_NEWS_EMAIL;
+ $page->subject = $this->subject;
+ $page->formData = $this->formData;
+ $page->eventAdminURL = BASE_URL.'admin/Events/list_events.phtml?pending=t';
+
+ $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)
+ {
+ try {
+ // need to set the dates up first
+ $this->formatValue($values['bdate'], '%02d/%02d/%d');
+ $this->formatValue($values['edate'], '%02d/%02d/%d');
+ $this->formatValue($values['btime'], '%02d:%02d %s');
+ $this->formatValue($values['etime'], '%02d:%02d %s');
+
+ $sql = Toolkit_Common::createSQLInsert(
+ $this->tableName,
+ array_keys($values)
+ );
+
+ return Toolkit_Common::processQuery($this->dbh, $sql, $values);
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($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 (preg_match('/^.+_rmv$/', $k)) {
+ unset($values[$k]);
+ }
+ }
+
+ 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}
', 'descr');
+ $renderer->setElementTemplate('
'.$required.'{label}'.$error.'{element}
', 'submit_rmv');
+
+ if ($this->useCaptcha) {
+ $renderer->setElementTemplate('
+
+
diff --git a/Toolkit/FileServer/AdapterAbstract.php b/Toolkit/FileServer/AdapterAbstract.php
new file mode 100644
index 0000000..92494cc
--- /dev/null
+++ b/Toolkit/FileServer/AdapterAbstract.php
@@ -0,0 +1,401 @@
+
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version CVS: $Id: AdapterAbstract.php,v 1.1 2012/02/03 19:04:13 matrix Exp $
+ * @link <>
+ * @see References to other sections (if any)...
+ */
+
+
+/**
+ * Validation Secret
+ */
+define('IS_VALIDATE_SECRET', 'Glm0IS1secreT');
+
+/**
+ * URL to file server, this is dynamic based on the server
+ * so can be setup for any sandbox
+ */
+define('IS_SUBMIT_URL', FILE_SERVER_URL . 'submit.phtml');
+
+/**
+ * Adapter class for linking to the file server
+ *
+ * @category FileServer
+ * @package Toolkit_FileServer
+ * @author Jamie Kahgee
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version Release: @package_version@
+ * @link <>
+ * @see References to other sections (if any)...
+ */
+abstract class Toolkit_FileServer_AdapterAbstract
+{
+ // {{{ properties
+
+ /**
+ * ID of owner that was setup in the file server
+ *
+ * This is defined via the file server web interface
+ * @var string
+ * @access protected
+ */
+ protected $ownerID;
+
+ /**
+ * Owners password that was setup for them
+ *
+ * This is defined via the file server web interface
+ * @var string
+ * @access protected
+ */
+ protected $ownerPW;
+
+ /**
+ * XML to send to the file server
+ * @var unknown
+ * @access protected
+ */
+ protected $xml;
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * @param string $owner File Server owner
+ * @param string $pword File Server owner password
+ */
+ public function __construct($owner = IS_OWNER_ID, $pword = IS_OWNER_PW)
+ {
+ $this->ownerID = $owner;
+ $this->ownerPW = $pword;
+ }
+
+ // }}}
+
+ // {{{ buildFileServerXML()
+
+ /**
+ * buildFileServerXML
+ *
+ * Create the xml for the FileServerRequest
+ *
+ * @param string $fName File name to upload or delete
+ * @param string $type Upload, Delete or URL
+ *
+ * @return string xml content
+ * @access protected
+ */
+ protected function buildFileServerXML($fName, $type)
+ {
+ $xml = new DOMDocument('1.0');
+ $xml->formatOutput = true;
+
+ $fileServerRequest = $xml->createElement('FileServerRequest');
+ $fileServerRequest->setAttribute('version', '1.0');
+
+ // access request
+ $accessRequest = $xml->createElement('AccessRequest');
+ $owner = $xml->createElement('Owner');
+ $ownerID = $xml->createElement('OwnerID', $this->ownerID);
+ $ownerPW = $xml->createElement('OwnerPW', $this->ownerPW);
+
+ $owner->appendChild($ownerID);
+ $owner->appendChild($ownerPW);
+
+ $accessRequest->appendChild($owner);
+
+ $fileServerRequest->appendChild($accessRequest);
+
+ $file = $this->getFileElement($xml, $type, $fName);
+
+ $fileServerRequest->appendChild($file);
+ $validStr = md5($this->ownerID . $this->ownerPW . IS_VALIDATE_SECRET);
+
+ $validation = $xml->createElement('Validation', $validStr);
+ $fileServerRequest->appendChild($validation);
+ $xml->appendChild($fileServerRequest);
+
+ return $xml->saveXML($xml);
+ }
+
+ // }}}
+
+ // {{{ delete()
+
+ /**
+ * Delete a file from the file server
+ *
+ * @param string $name File name
+ *
+ * @return string file name
+ * @access public
+ * @throws Toolkit_FileServer_Exception
+ */
+ public function delete($name)
+ {
+ $ch = curl_init();
+
+ $fileData = array(
+ 'request' => $this->buildFileServerXML($name, 'Delete')
+ );
+ $curlOptions = array(
+ CURLOPT_URL => IS_SUBMIT_URL,
+ CURLOPT_HEADER => 0,
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_POSTFIELDS => $fileData
+ );
+ curl_setopt_array($ch, $curlOptions);
+
+ $response = curl_exec($ch);
+ curl_close($ch);
+
+ try {
+ $xmlDoc = new DOMDocument;
+ $response = str_replace('', '', $response);
+ $xmlDoc->loadXML($response);
+ $successCode = $this->xmlPathContent(
+ $xmlDoc,
+ '/FileServerResponse/ReplyStatus/SuccessCode'
+ );
+ $message = $this->xmlPathContent(
+ $xmlDoc,
+ '/FileServerResponse/ReplyStatus/Message'
+ );
+
+ if ($successCode != 0) {
+ throw new RangeException(
+ "Invalid response `$response` - `$message`"
+ );
+ }
+
+ return $message;
+ } catch (RangeException $e) {
+ Toolkit_Logger::logException('Image Server', $e);
+ throw new Toolkit_FileServer_Exception(
+ 'Invalid File Server Response'
+ );
+ }
+ }
+
+ // }}}
+
+ // {{{ getFileElement()
+
+
+ /**
+ * Gets the file element used in the XML sent to the file server
+ *
+ * @param DOMDocument $xml DOM object used to build the xml string
+ * @param string $type Type of manipulation (Upload, URL, Delete)
+ * @param string $fName File name
+ *
+ * @return DOMElement $file File xml element
+ * @access protected
+ */
+ abstract protected function getFileElement(
+ DOMDocument $xml,
+ $type,
+ $fName
+ );
+
+ // }}}
+ // {{{ getErrorMessage()
+
+ /**
+ * Gets an appropriate error message for file upload errors
+ *
+ * @param integer Error code
+ *
+ * @return string Error message
+ * @access protected
+ */
+ protected function getErrorMessage($code)
+ {
+ switch ($code) {
+ case UPLOAD_ERR_INI_SIZE :
+ $message = 'The Uploaded file exceeds the upload max filesize directive in php.ini';
+ break;
+
+ case UPLOAD_ERR_FORM_SIZE :
+ $message = 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form';
+ break;
+
+ case UPLOAD_ERR_PARTIAL :
+ $message = 'The uploaded file was only partially uploaded';
+ break;
+
+ case UPLOAD_ERR_NO_FILE :
+ $message = 'No file was uploaded';
+ break;
+
+ case UPLOAD_ERR_NO_TMP_DIR :
+ $message = 'Missing a temporary folder';
+ break;
+
+ case UPLOAD_ERR_CANT_WRITE :
+ $message = 'Failed to write file to disk';
+ break;
+
+ case UPLOAD_ERR_EXTENSION :
+ $message = 'A PHP extension stopped the file upload';
+ break;
+
+ default :
+ $message = 'Unknown error uploading file';
+ break;
+ }
+
+ return $message;
+ }
+
+ // }}}
+
+ // {{{ upload()
+
+ /**
+ * Upload a file to the File Server
+ *
+ * @param string $name $_FILES index key that holds the file data
+ *
+ * @return array Uploaded file data
+ * @access public
+ * @throws Toolkit_FileServer_Exception
+ */
+ public function upload($name)
+ {
+ $fileType = null;
+ if (preg_match('/^http/', $name)) {
+ $fileType = 'URL';
+ } elseif (isset($_FILES[$name]) && is_array($_FILES[$name])) {
+ $fileType = 'Upload';
+ }
+
+ if ($_FILES[$name]['error'] != 0) {
+ $message = $this->getErrorMessage($_FILES[$name]['error']);
+ throw new Toolkit_FileServer_Exception(
+ $message,
+ $_FILES[$name]['error']
+ );
+ }
+
+ if (is_null($fileType)) {
+ return false;
+ } else {
+ $request = $this->buildFileServerXML($name, $fileType);
+
+ $ch = curl_init();
+ if ($fileType == 'URL') {
+ $fileData = array(
+ 'request' => $request
+ );
+ } else {
+ $fileData = array(
+ 'request' => $request,
+ 'file_upload' => "@{$_FILES[$name]['tmp_name']}",
+ 'file_upload_name' => $_FILES[$name]['name']
+ );
+ }
+
+ $curlOptions = array(
+ CURLOPT_URL => IS_SUBMIT_URL,
+ CURLOPT_HEADER => 0,
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_POSTFIELDS => $fileData
+ );
+ curl_setopt_array($ch, $curlOptions);
+
+ $response = curl_exec($ch);
+ curl_close($ch);
+
+ try {
+ $xmlDoc = new DOMDocument();
+ $response = str_replace('', '', $response);
+ $xmlDoc->loadXML($response);
+ $successCode = $this->xmlPathContent(
+ $xmlDoc,
+ '/FileServerResponse/ReplyStatus/SuccessCode'
+ );
+ $message = $this->xmlPathContent(
+ $xmlDoc,
+ '/FileServerResponse/ReplyStatus/Message'
+ );
+ $storedName = $this->xmlPathContent(
+ $xmlDoc,
+ '/FileServerResponse/File/StoredName'
+ );
+ $storedSize = $this->xmlPathContent(
+ $xmlDoc,
+ '/FileServerResponse/File/StoredSize'
+ );
+ $mediaType = $this->xmlPathContent(
+ $xmlDoc,
+ '/FileServerResponse/File/MediaType'
+ );
+
+ if ($successCode != 0) {
+ throw new RangeException(
+ "Invalid response `$response` - `$message`"
+ );
+ }
+
+ $extension = end(explode('.', $storedName));
+ return array(
+ 'name' => $storedName,
+ 'size' => $storedSize,
+ 'type' => $mediaType,
+ 'extension' => $extension,
+ );
+ } catch (RangeException $e) {
+ Toolkit_Logger::logException('Image Server', $e);
+ throw new Toolkit_FileServer_Exception(
+ 'Invalid File Server Response'
+ );
+ }
+ }
+ }
+
+ // }}}
+
+ // {{{ xmlPathContent()
+
+ /**
+ * Extract a XML node value
+ *
+ * @param DOMDocument $dom DOM object holding the XML
+ * @param string $content Node name to extract content from
+ *
+ * @return mixed Node value on success, false if can't find the value
+ * @access protected
+ */
+ protected function xmlPathContent(DOMDocument $dom, $content)
+ {
+ $xPath = new DOMXPath($dom);
+ $nodeList = $xPath->query($content);
+ if ($nodeList->length > 0) {
+ $node = $nodeList->item(0);
+ return $node->nodeValue;
+ }
+
+ return false;
+ }
+
+ // }}}
+}
diff --git a/Toolkit/FileServer/Exception.php b/Toolkit/FileServer/Exception.php
new file mode 100644
index 0000000..8739c0f
--- /dev/null
+++ b/Toolkit/FileServer/Exception.php
@@ -0,0 +1,5 @@
+
diff --git a/Toolkit/FileServer/FileAdapter.php b/Toolkit/FileServer/FileAdapter.php
new file mode 100644
index 0000000..14ea220
--- /dev/null
+++ b/Toolkit/FileServer/FileAdapter.php
@@ -0,0 +1,101 @@
+
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version CVS: $Id: FileAdapter.php,v 1.1 2012/02/03 19:04:13 matrix Exp $
+ * @link <>
+ * @see References to other sections (if any)...
+ */
+
+/**
+ * File Adapter
+ *
+ * Used for linking to the file server for file uploading, storage and deletion
+ *
+ * @category FileServer
+ * @package Toolkit_FileServer
+ * @author Jamie Kahgee
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version Release: @package_version@
+ * @link <>
+ * @see References to other sections (if any)...
+ */
+class Toolkit_FileServer_FileAdapter extends Toolkit_FileServer_AdapterAbstract
+{
+ // {{{ getFileElement()
+
+ /**
+ * Creates the file element for the XML string
+ *
+ * @param DOMDocument $xml XML object used to build the string
+ * @param string $type Type of action to take on the file (Upload, Delete)
+ * @param string $fName file name to delete
+ *
+ * @return DOMElement $file File xml element
+ * @access protected
+ * @throws RuntimeException
+ */
+ protected function getFileElement(DOMDocument $xml, $type, $fName)
+ {
+ $file = $xml->createElement('File');
+
+ switch ($type) {
+ case 'Upload' :
+ $action = $xml->createElement('FileAction', 'Submit');
+ $delivery = $xml->createElement('DeliveryMethod', 'Submit');
+ $fieldName = $xml->createElement('FieldName', 'file_upload');
+
+ $fileName = filter_var($_FILES[$fName]['name'], FILTER_SANITIZE_STRING);
+ $nameParts = explode('.', $fileName);
+ $extension = end($nameParts);
+ $fieldName = $xml->createElement('Extension', end($nameParts));
+
+ $file->appendChild($action);
+ $file->appendChild($delivery);
+ $file->appendChild($fieldName);
+ break;
+
+ case 'URL':
+ $action = $xml->createElement('FileAction', 'Submit');
+ $delivery = $xml->createElement('DeliveryMethod', 'URL');
+ $src = $xml->createElement('Src', $fName);
+
+ $nameParts = explode('.', $fName);
+ $extension = end($nameParts);
+ $fieldName = $xml->createElement('Extension', end($nameParts));
+
+ $file->appendChild($action);
+ $file->appendChild($delivery);
+ $file->appendChild($src);
+ $file->appendChild($fieldName);
+ break;
+
+ case 'Delete' :
+ $action = $xml->createElement('FileAction', 'Delete');
+ $file->appendChild($action);
+
+ $fileName = $xml->createElement('FileName', $fName);
+ $file->appendChild($fileName);
+ break;
+
+ default :
+ throw new RuntimeException("Invalid XML type - `$type`.");
+ break;
+ }
+
+ return $file;
+ }
+
+ // }}}
+}
diff --git a/Toolkit/FileServer/ImageAdapter.php b/Toolkit/FileServer/ImageAdapter.php
new file mode 100644
index 0000000..0d31fab
--- /dev/null
+++ b/Toolkit/FileServer/ImageAdapter.php
@@ -0,0 +1,248 @@
+
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version CVS: $Id: ImageAdapter.php,v 1.1 2012/02/03 19:04:13 matrix Exp $
+ * @link <>
+ * @see References to other sections (if any)...
+ */
+
+/**
+ * Image Adapter
+ *
+ * Used for linking to the file server for image uploading, storage and deletion
+ *
+ * @category FileServer
+ * @package Toolkit_FileServer
+ * @author Jamie Kahgee
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version Release: @package_version@
+ * @link <>
+ * @see References to other sections (if any)...
+ */
+class Toolkit_FileServer_ImageAdapter extends Toolkit_FileServer_AdapterAbstract
+{
+ // {{{ getAllowedMimeTypes()
+
+ /**
+ * Get the mime types that are allowed to be uploaded
+ *
+ * @return array allowed mime types
+ */
+ public function getAllowedMimeTypes()
+ {
+ return array(
+ 'image/jpe',
+ 'image/jpeg',
+ 'image/jpg',
+ 'image/jfif',
+ 'image/pjpeg',
+ 'image/pjp',
+ 'image/gif',
+ 'image/gif',
+ 'image/png',
+ );
+ }
+
+ // }}}
+ // {{{ getFileElement()
+
+ /**
+ * Creates the file element for the XML string
+ *
+ * @param DOMDocument $xml XML object used to build the string
+ * @param string $type Type of action to take on the file (Upload, Delete)
+ * @param string $fName file name to delete
+ *
+ * @return DOMElement $file File xml element
+ * @access protected
+ * @throws RuntimeException
+ */
+ protected function getFileElement(DOMDocument $xml, $type, $fName)
+ {
+ $file = $xml->createElement('File');
+
+ switch ($type) {
+ case 'Upload' :
+ $action = $xml->createElement('FileAction', 'Submit');
+ $delivery = $xml->createElement('DeliveryMethod', 'Submit');
+ $fieldName = $xml->createElement('FieldName', 'file_upload');
+
+ $file->appendChild($action);
+ $file->appendChild($delivery);
+ $file->appendChild($fieldName);
+ break;
+
+ case 'URL':
+ $action = $xml->createElement('FileAction', 'Submit');
+ $delivery = $xml->createElement('DeliveryMethod', 'URL');
+ $src = $xml->createElement('Src', $fName);
+
+ $file->appendChild($action);
+ $file->appendChild($delivery);
+ $file->appendChild($src);
+ break;
+
+ case 'Delete':
+ $action = $xml->createElement('FileAction', 'Delete');
+ $file->appendChild($action);
+
+ $fileName = $xml->createElement('FileName', $fName);
+ $file->appendChild($fileName);
+ break;
+
+ default :
+ throw new RuntimeException("Invalid XML type - `$type`.");
+ break;
+ }
+
+ return $file;
+ }
+
+ // }}}
+ // {{{ getImageSize()
+
+ /**
+ * getImageSize
+ *
+ * Return image data on an image from image server
+ *
+ * @param string $image Full URI to image
+ * http://is0/userId/imageStyle/imageName
+ * Must be a full URI including an authority.
+ * No relative URIs, the // are mandatory
+ *
+ * @return array Image data 0 => width, 1 => height, 2 => html
+ * @access public
+ * @throws Exception
+ */
+ public function getImageSize($image)
+ {
+ $options = array('allowed_schemes' => array('http','https'));
+ if (!Validate::uri($image, $options)) {
+ throw new Exception('Invalid URI for the image');
+ }
+
+ $ch = curl_init();
+ $curlOptions = array(
+ CURLOPT_URL => "{$image}/info",
+ CURLOPT_HEADER => 0,
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_POSTFIELDS => $fileData
+ );
+ curl_setopt_array($ch, $curlOptions);
+
+ $response = curl_exec($ch);
+ curl_close($ch);
+
+ if (!@simplexml_load_string($response)) {
+ $logger = Toolkit_Logger::getLogger();
+ $logger->warning("$response - $image");
+ }
+
+ $wPattern = '/(.*)<\/width>/';
+ preg_match($wPattern, $response, $matches);
+ $width = $matches[1];
+ $hPattern = '/(.*)<\/height>/';
+ preg_match($hPattern, $response, $matches);
+ $height = $matches[1];
+ $html = "width=\"{$width}\" height=\"{$height}\"";
+ return array($width, $height, $html);
+ }
+
+ // }}}
+ // {{{ uploadImageFile()
+
+ /**
+ * Upload a file to the File Server
+ *
+ * @param string $fname full path to image file
+ *
+ * @return array Uploaded file data
+ * @access public
+ * @throws Toolkit_FileServer_Exception
+ */
+ public function uploadImageFile($fname)
+ {
+ if (!file_exists($fname)) {
+ throw new RuntimeException("could not find file `$fname`");
+ }
+
+ $request = $this->buildFileServerXML(basename($fname), 'Upload');
+
+ $ch = curl_init();
+ $fileData = array(
+ 'request' => $request,
+ 'file_upload' => "@$fname",
+ 'file_upload_name' => basename($fname)
+ );
+
+ $curlOptions = array(
+ CURLOPT_URL => IS_SUBMIT_URL,
+ CURLOPT_HEADER => 0,
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_POSTFIELDS => $fileData
+ );
+ curl_setopt_array($ch, $curlOptions);
+
+ $response = curl_exec($ch);
+ curl_close($ch);
+
+ try {
+ $xmlDoc = new DOMDocument();
+ $response = str_replace('', '', $response);
+ $xmlDoc->loadXML($response);
+ $successCode = $this->xmlPathContent(
+ $xmlDoc,
+ '/FileServerResponse/ReplyStatus/SuccessCode'
+ );
+ $message = $this->xmlPathContent(
+ $xmlDoc,
+ '/FileServerResponse/ReplyStatus/Message'
+ );
+ $storedName = $this->xmlPathContent(
+ $xmlDoc,
+ '/FileServerResponse/File/StoredName'
+ );
+ $storedSize = $this->xmlPathContent(
+ $xmlDoc,
+ '/FileServerResponse/File/StoredSize'
+ );
+ $mediaType = $this->xmlPathContent(
+ $xmlDoc,
+ '/FileServerResponse/File/MediaType'
+ );
+
+ if ($successCode != 0) {
+ throw new RangeException(
+ "Invalid response `$response` - `$message`"
+ );
+ }
+
+ return array(
+ 'name' => $storedName,
+ 'size' => $storedSize,
+ 'type' => $mediaType,
+ );
+ } catch (RangeException $e) {
+ Toolkit_Logger::logException('Image Server', $e);
+ throw new Toolkit_FileServer_Exception(
+ 'Invalid File Server Response'
+ );
+ }
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/FileServer/Mock/ImageAdapter.php b/Toolkit/FileServer/Mock/ImageAdapter.php
new file mode 100644
index 0000000..9479eef
--- /dev/null
+++ b/Toolkit/FileServer/Mock/ImageAdapter.php
@@ -0,0 +1,125 @@
+
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version CVS: $Id: ImageAdapter.php,v 1.1 2012/02/03 19:04:13 matrix Exp $
+ * @link <>
+ * @see References to other sections (if any)...
+ */
+
+/**
+ * Mock Image Adapter
+ *
+ * Mocks uploading and deleting images from the image server
+ * This script prevents unneeded resources from being uploaded
+ * or deleted from the file server
+ *
+ * @category FileServer
+ * @package Toolkit_FileServer
+ * @author Jamie Kahgee
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version Release: @package_version@
+ * @link <>
+ * @see References to other sections (if any)...
+ */
+class Toolkit_FileServer_Mock_ImageAdapter
+ extends Toolkit_FileServer_ImageAdapter
+{
+ // {{{ getImageSize()
+
+ /**
+ * getImageSize
+ *
+ * Return image data on an image from image server
+ *
+ * @param string $image Full URI to image
+ * http://is0/userId/imageStyle/imageName
+ * Must be a full URI including an authority.
+ * No relative URIs, the // are mandatory
+ *
+ * @return array Image data 0 => width, 1 => height, 2 => html
+ * @access public
+ * @throws Exception
+ */
+ public function getImageSize($image)
+ {
+ $width = $height = 1;
+ $html = "width=\"{$width}\" height=\"{$height}\"";
+ return array($width, $height, $html);
+ }
+
+ // }}}
+ // {{{ uploadImageFile()
+
+ /**
+ * Upload a file to the File Server
+ *
+ * @param string $fname full path to image file
+ *
+ * @return array Uploaded file data
+ * @access public
+ * @throws Toolkit_FileServer_Exception
+ */
+ public function uploadImageFile($fname)
+ {
+ return array(
+ 'name' => 'is00-mock-image.jpg',
+ 'size' => 100,
+ 'type' => 'image/jpeg',
+ );
+ }
+
+ // }}}
+ // {{{ upload()
+
+ /**
+ * Upload a file to the File Server
+ *
+ * @param string $name $_FILES index key that holds the file data
+ *
+ * @return array Uploaded file data
+ * @access public
+ * @throws Toolkit_FileServer_Exception
+ */
+ public function upload($name)
+ {
+ return array(
+ 'name' => 'is00-mock-image.jpg',
+ 'size' => 100,
+ 'type' => 'image/jpeg',
+ );
+ }
+
+ // }}}
+ // {{{ delete()
+
+ /**
+ * Delete a file from the file server
+ *
+ * @param string $name File name
+ *
+ * @return string file name
+ * @access public
+ * @throws Toolkit_FileServer_Exception
+ */
+ public function delete($name)
+ {
+ return true;
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/FlexyDataGridBuilder.php b/Toolkit/FlexyDataGridBuilder.php
new file mode 100644
index 0000000..4127582
--- /dev/null
+++ b/Toolkit/FlexyDataGridBuilder.php
@@ -0,0 +1,207 @@
+
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: FlexyDataGridBuilder.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link <>
+ */
+
+/**
+ * Create Flexy templating Datagrids for displaying data
+ *
+ * This abstract class handles all the base functionality of creating
+ * handeling all the details associated w/ a Flexy template datagrid
+ * 1. Creation
+ * 2. Sorting (via column headers or sortform)
+ * 3. Pagenation
+ *
+ * @category Structures
+ * @package Toolkit_FlexyDataGridBuilder
+ * @author Jamie Kahgee
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com/Gaslightmedia Gaslightmedia
+ * @link http://pear.php.net/package/Structures_DataGrid/docs
+ * @see Structures_DataGrid_Renderer_Flexy, HTML_Template_Flexy
+ */
+abstract class Toolkit_FlexyDataGridBuilder extends Toolkit_DataGridBuilder
+{
+ // {{{ properties
+
+ /**
+ * Name of the table which we will be dealing with
+ *
+ * @var string
+ * @access protected
+ */
+ protected $tableName;
+
+ /**
+ * The name of the template that renders this datagrid
+ *
+ * @var string
+ * @access protected
+ */
+ protected $template;
+
+ /**
+ * Output an object as $t to the template
+ *
+ * converts array keys to objects usable in a template form.
+ *
+ *
+ * $this->ctrlObj['url'] = BASE_URL;
+ *
+ *
+ *
+ *
+ *
+ *
+ * @var array
+ * @access protected
+ */
+ protected $ctrlObj = array();
+
+ /**
+ * Rendering options for DataGrid
+ *
+ * @var array
+ * @access protected
+ */
+ protected $rendererOptions = array(
+ 'sortIconASC' => '⇑',
+ 'sortIconDESC' => '⇓',
+ 'sortingResetsPaging' => false,
+ );
+
+ /**
+ * The HTML id of the DataGrid
+ *
+ * @var string
+ * @access protected
+ */
+ protected $gridId = 'dataGrid';
+
+ /**
+ * The HTML class of the DataGrid
+ *
+ * @var string
+ * @access protected
+ */
+ protected $gridClass = 'dataGrid';
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * Builds the DataGrid class.
+ *
+ * @param PDO $pdo PDO object used in the datagrid
+ * @param integer $limit The number of records to display per page.
+ * @param integer $page The current page view. In most cases,
+ * this is useless. Note: if you specify
+ * this, the "page"GET variable will be ignored.
+ * @param string $rendererType The type of renderer to use. You may
+ * prefer to use the $type argument of
+ * render, fill or getOutput.
+ *
+ * @return void
+ * @access public
+ */
+ public function __construct(
+ PDO $pdo,
+ $limit = null,
+ $page = null,
+ $rendererType = null
+ ) {
+ $this->dbh = $pdo;
+ if (ctype_digit($_GET['setPerPage'])) {
+ $limit = $_GET['setPerPage'];
+ }
+
+ parent::__construct($pdo, $limit, $page, $rendererType);
+
+ // If all records show on one page, then hide sort form.
+ if (!is_null($limit)) {
+ $this->sortableAfter = $limit;
+ }
+ }
+
+ // }}}
+
+ // {{{ show()
+
+ /**
+ * Displays the DataGrid results
+ *
+ * @param Structures_DataGrid_Renderer_Flexy $renderer Rendering engine used to render DG
+ *
+ * @return void
+ * @access public
+ */
+ public function show(Structures_DataGrid_Renderer_Flexy $renderer)
+ {
+ echo $this->toHtml($renderer);
+ }
+
+ // }}}
+
+ // {{{ toHtml()
+
+ /**
+ * Returns the DataGrid
+ *
+ * @param Structures_DataGrid_Renderer_Flexy $renderer Rendering engine used to render DG
+ *
+ * @return string html templated datagrid results
+ * @access public
+ */
+ public function toHtml(Structures_DataGrid_Renderer_Flexy $renderer)
+ {
+ $this->configureColumns();
+
+ try {
+ $bind = $this->bind($this->sql, $this->options, 'PDO');
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+
+ if (PEAR::isError($bind)) {
+ return Toolkit_Common::handleError($bind);
+ }
+
+ if (method_exists($this, 'setControlObject')) {
+ $this->setControlObject();
+ foreach ($this->ctrlObj as $k => $v) {
+ $renderer->$k = $v;
+ }
+ }
+
+ $renderer->setOptions($this->rendererOptions);
+ $renderer->setOptions(array('pagerOptions' => $this->pagerOptions));
+
+ $this->attachRenderer($renderer);
+ $tpl = $renderer->getContainer();
+ $tpl->compile($this->template);
+
+ // Get the entire datagrid body.
+ $gridBody = $this->getOutput();
+ if (PEAR::isError($gridBody)) {
+ return Tolkit_Common::handleError($gridBody);
+ }
+
+ return $gridSorter . $gridBody;
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Form.php b/Toolkit/Form.php
new file mode 100644
index 0000000..e5c0238
--- /dev/null
+++ b/Toolkit/Form.php
@@ -0,0 +1,144 @@
+
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: Form.php,v 1.1.1.1 2009/09/17 20:08:55 matrix Exp $
+ * @link http://demo.gaslightmedia.com/
+ */
+
+/**
+ * Minimum form object method definitions
+ *
+ * Each form must at least define some elements and setup the rules for
+ * that form. They must also create a method which handless extracting
+ * the form object into an html string suitable to be displayed onto a
+ * page.
+ *
+ * @category Form
+ * @package Toolkit_Form
+ * @author Jamie Kahgee
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com/
+ */
+interface Toolkit_Form
+{
+ // {{{ configureElements()
+
+ /**
+ * Defines all elements to be used in a form
+ *
+ * Creates an array of elements and passes them off to the setupElements
+ * function wich adds each element to the form object.
+ *
+ *
+ * public function configureElements()
+ * {
+ * $e = array();
+ *
+ * $e[] = array(
+ * 'type' => 'text',
+ * 'req' => false
+ * 'name' => 'text_field',
+ * 'display' => 'Text Label',
+ * );
+ * $e[] = array(
+ * 'type' => 'checkbox',
+ * 'req' => false
+ * 'name' => 'checkbox_field',
+ * 'display' => 'Checkbox Label',
+ * );
+ *
+ * // ... More Element Definitions
+ *
+ * $this->setupElements($e);
+ * }
+ *
+ *
+ * @access public
+ * @return void
+ */
+ //public function configureElements();
+
+ // }}}
+ // {{{ configureForm()
+
+ /**
+ * Calls all the configuration methods to configure a form for use
+ *
+ * @access public
+ * @return void
+ */
+ //public function configureForm();
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Defines all element rules to be used for validation in the form
+ *
+ * At the bare minimum, this function needs to be called to setup the
+ * form rules, even if no extra rules are defined. Because it still
+ * creates all the required rules that are defined w/ each element.
+ *
+ *
+ * public function configureRules()
+ * {
+ * $r = array();
+ *
+ * $r[] = array(
+ * 'element' => 'text_field',
+ * 'message' => 'ERROR: 10 characters max!',
+ * 'type' => 'maxlength',
+ * 'format' => 10,
+ * 'validation' => $this->validationType,
+ * 'reset' => true,
+ * 'force' => false,
+ * );
+ * $r[] = array(
+ * 'element' => 'text_field',
+ * 'message' => 'ERROR: Numric characters only!',
+ * 'type' => 'numeric',
+ * 'format' => null,
+ * 'validation' => $this->validationType,
+ * 'reset' => true,
+ * 'force' => false,
+ * );
+ *
+ * // ... More Rule Definitions
+ *
+ * $this->setupRules($r);
+ * }
+ *
+ *
+ * @access public
+ * @return void
+ */
+ public function configureRules();
+
+ // }}}
+ // {{{ toHtml()
+
+ /**
+ * Get an html string that contains the form
+ *
+ * Check if the form needs to be validated (ie. it was submitted)
+ * Check if submitted data needs to be processed
+ *
+ * @access public
+ * @return string an html string that contains the entire form
+ */
+ public function toHtml();
+
+ // }}}
+}
+?>
diff --git a/Toolkit/FormBuilder.php b/Toolkit/FormBuilder.php
new file mode 100644
index 0000000..3f51aad
--- /dev/null
+++ b/Toolkit/FormBuilder.php
@@ -0,0 +1,1183 @@
+
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: FormBuilder.php,v 1.2 2009/12/15 20:18:15 jamie Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Allow the inclusion of the Element Grid plugin for QuickForms
+ */
+require_once 'HTML/QuickForm/ElementGrid.php';
+
+/**
+ * Handle QuickForm CAPTCHA's
+ */
+require_once 'HTML/QuickForm/CAPTCHA/Image.php';
+
+/**
+ * Require PEAR QuickForm class
+ */
+require_once 'HTML/QuickForm.php';
+
+require_once 'HTML/QuickForm/Rule/Zip.php';
+require_once 'HTML/QuickForm/Rule/Phone.php';
+require_once 'HTML/QuickForm/Rule/Banwords.php';
+require_once 'HTML/QuickForm/Rule/State.php';
+
+/**
+ * Base functionality for creating HTML_Quickforms
+ *
+ * @category Forms
+ * @package Toolkit_FormBuilder
+ * @author Jamie Kahgee
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+abstract class Toolkit_FormBuilder extends HTML_QuickForm
+{
+ // {{{ properties
+
+ /**
+ * Global form captcha question element
+ *
+ * @var object
+ * @access protected
+ */
+ protected $captchaQuestion;
+
+ /**
+ * Global form captcha answer from user
+ *
+ * @var object
+ * @access protected
+ */
+ protected $captchaAnswer;
+
+ /**
+ * Form submitted data used when emailing form results
+ *
+ * @var array
+ * @access protected
+ */
+ protected $formData = array();
+
+ /**
+ * Automatically create validation rules for any date elements
+ *
+ * This will only work if the date element is in m-d-Y format
+ *
+ * @var boolean
+ * @access protected
+ */
+ protected $autoValidateDateElements = true;
+
+ /**
+ * How do we want to validate the form
+ *
+ * Possible options are [server, client]
+ *
+ * @var string
+ * @access protected
+ */
+ protected $validationType = 'server';
+
+ /**
+ * What do you want the error msg to be if the form doesn't validate
+ *
+ * @var string
+ * @access protected
+ */
+ protected $errorMsg
+ = '
+ Warning: The form was not sent, please review the errors below.
+
';
+
+ /**
+ * What do you want the success msg to be if the form validates successfully
+ *
+ * @var string
+ * @access protected
+ */
+ protected $successMsg
+ = '
+ The information below has been successfully submitted.
+
';
+
+ /**
+ * Whether uploaded files should be processed too (if present)
+ *
+ * @var string
+ * @access protected
+ */
+ protected $mergeFiles = true;
+
+ /**
+ * Include a captcha on the form or not
+ *
+ * @var boolean
+ * @access protected
+ */
+ protected $useCaptcha;
+
+ /**
+ * The default templates to inject into the form renderer
+ *
+ * @var string
+ * @access protected
+ */
+ protected $template;
+
+ /**
+ * The default rules to register for validating
+ *
+ * We have to register these rules, or any others we want, before
+ * we are able to use them in our forms.
+ *
+ * These rules can be removed in subclasses before the rules are configured
+ * if you want to omit any of them from validating input - just remember
+ * to not call them in your configured rules!
+ *
+ * Phone: validates input against US and CA style phone #'s
+ *
+ * $rules[] = array('element' => 'phone',
+ * 'message' => 'ERROR: Invalid Phone Format!',
+ * 'type' => 'phone',
+ * 'format' => null,
+ * 'validation' => $this->validationType,
+ * 'reset' => true,
+ * 'force' => false);
+ *
+ *
+ * Zip: Validates input against US and CA zip codes, if DB check is
+ * set to true, validate zip codes against all the zip codes in the
+ * DB.
+ *
+ * $rules[] = array('element' => 'zip',
+ * 'message' => 'ERROR: Invalid Zip!',
+ * 'type' => 'zip',
+ * 'format' => array('requireDBCheck' => true),
+ * 'validation' => $this->validationType,
+ * 'reset' => true,
+ * 'force' => false);
+ *
+ *
+ * Banwords: Make sure each each doesn't contain a banned word. Checking
+ * against a DB of banned words.
+ *
+ * State: Validate input against US and CA region / province codes. If DB
+ * check is set to true, validate region / province against all the
+ * regions / provinces in the DB.
+ *
+ * $rules[] = array('element' => 'state_id',
+ * 'message' => 'ERROR: Invalid State / Province!',
+ * 'type' => 'state',
+ * 'format' => array('requireDBCheck' => true),
+ * 'validation' => $this->validationType,
+ * 'reset' => true,
+ * 'force' => false);
+ *
+ *
+ * @var array
+ * @access protected
+ * @see app.gaslightmedia.com/glmPEAR/HTML/QuickForm/Rule/Zip.php
+ * @see app.gaslightmedia.com/glmPEAR/HTML/QuickForm/Rule/Phone.php
+ * @see app.gaslightmedia.com/glmPEAR/HTML/QuickForm/Rule/Banwords.php
+ * @see app.gaslightmedia.com/glmPEAR/HTML/QuickForm/Rule/State.php
+ */
+ protected $registeredRules = array('phone', 'zip', 'state');
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Class constructor
+ *
+ * @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
+ * @link http://pear.php.net/package/HTML_QuickForm/docs/latest/HTML_QuickForm/HTML_QuickForm.html
+ * @see HTML_QuickForm
+ * @todo Remove assigning the dbh the global dbh and setup a PDO
+ * to be passed in from a parameter - this will allow for easier
+ * PHPUnit testing
+ */
+ public function __construct(
+ $formName,
+ $method = 'post',
+ $action = '',
+ $target = '',
+ $attributes = null,
+ $trackSubmit = false
+ ) {
+ // T_VARIABLE error when passing this server
+ // var in on the constructors params.
+ $action = empty($action) ? $_SERVER['REQUEST_URI'] : $action;
+ parent::__construct(
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+ $this->template = BASE . 'templates/forms/';
+ $this->dbh = Toolkit_Database::getInstance();
+ }
+
+ // }}}
+ // {{{ __destruct()
+
+ /**
+ * Destructor
+ *
+ * @return void
+ * @access public
+ * @todo remove the need to unset any dbh's, they should be passed in
+ * via parameters if they are needed.
+ */
+ public function __destruct()
+ {
+ }
+
+ // }}}
+
+ // {{{ addCharLimit()
+
+ /**
+ * adds a maxlength character limitation to an element
+ *
+ * @param string $element The name of the element to add
+ * the char limit to
+ * @param integer $limit The number of characters allowed
+ *
+ * @return void
+ * @access public
+ */
+ public function addCharLimit($element, $limit)
+ {
+ $this->addRule(
+ $element,
+ "ERROR: $limit characters max!",
+ 'maxlength',
+ $limit,
+ 'server'
+ );
+ // Add a maxlength attribute to the field on the form
+ // which will help prevent users from sending over 100 chars
+ // to the server in the first place.
+ if ($this->getElementType($element) == 'text') {
+ $e =& $this->getElement($element);
+ $e->setMaxLength($limit);
+ }
+ }
+
+ // }}}
+ // {{{ apiVersion()
+
+ /**
+ * Returns the current FormBuilder API version
+ *
+ * @since 1.10
+ * @access public
+ * @return float
+ */
+ public function version()
+ {
+ return 1.1;
+ }
+
+ // }}}
+
+ // {{{ checkDateInput()
+
+ /**
+ * Checks the validation of a m-d-Y date
+ *
+ * This function will only be called if the autoValidateDateElements
+ * property is set to true.
+ *
+ * @param array $value Date element from form.
+ *
+ * @return boolean
+ * @access public
+ * @see Toolkit_FormBuilder->autoValidateDateElements
+ */
+ public function checkDateInput($value)
+ {
+ if ( empty($value['m'])
+ || empty($value['d'])
+ || empty($value['Y'])
+ ) {
+ return false;
+ }
+ return checkdate($value['m'], $value['d'], $value['Y']);
+ }
+
+ // }}}
+ // {{{ cleanElements()
+
+ /**
+ * Removes elements from form
+ *
+ * Loops through elements and if any names end in '_rmv' they are removed
+ * from the form object.
+ *
+ * Dynamically finds all elements on a form and removes any that
+ * end in '_rmv'. This can be really usefull if you want to display
+ * from results after the form was successfully submitted and validated,
+ * but don't need to display any extra form elements initially displayed
+ * on the form (like email confirmation fields, or static instruction
+ * elements).
+ *
+ * @param array $elements Form elements.
+ *
+ * @return void
+ * @access protected
+ */
+ protected function cleanElements($elements)
+ {
+ if (is_array($elements)) {
+ foreach ($elements as $e) {
+ if ($e['type'] == 'group') {
+ $this->cleanGroup($e['name']);
+ } elseif (preg_match('/^.+_rmv$/', $e['name'])) {
+ $this->removeElement($e['name']);
+ }
+ }
+ }
+ }
+
+ // }}}
+ // {{{ cleanForm()
+
+ /**
+ * Removes elements from form
+ *
+ * Dynamically finds all elements on a form and removes any that
+ * end in '_rmv'. This can be really usefull if you want to display
+ * from results after the form was successfully submitted and validated,
+ * but don't need to display any extra form elements initially displayed
+ * on the form (like email confirmation fields, or static instruction
+ * elements).
+ *
+ * @return void
+ * @access protected
+ */
+ protected function cleanForm()
+ {
+ $formArray = $this->toArray();
+ if (array_key_exists('sections', $formArray)) {
+ foreach ($formArray['sections'] as $k) {
+ if (preg_match('/^.+_rmv$/', $k['name'])) {
+ $this->removeElement($k['name']);
+ }
+ $this->cleanElements($k['elements']);
+ }
+ } else {
+ $this->cleanElements($formArray['elements']);
+ }
+ }
+
+ // }}}
+ // {{{ cleanGroup()
+
+ /**
+ * Removes any elements from a group that have names that end in '_rmv'
+ *
+ * @param string $name The name of the group element
+ *
+ * @return void
+ * @access protected
+ */
+ protected function cleanGroup($name)
+ {
+ $e =& $this->getElement($name);
+ $g =& $e->getElements();
+ $i = 0;
+ while ($name = $e->getElementName($i++)) {
+ if (preg_match('/^.+_rmv/', $name)) {
+ unset($g[($i - 1)]);
+ }
+ }
+ }
+
+ // }}}
+ // {{{ createGridElement()
+
+ /**
+ * Creates a grid element for the form
+ *
+ * Written so this can be overridden easily in subclasses later if needed!
+ *
+ * @param string $elementType QuickForm ElementGrid element definition
+ *
+ * @return mixed ElementGrid element.
+ * @access protected
+ */
+ protected function &createGridElement($elementType)
+ {
+ $args = func_get_args();
+ return call_user_func_array(array($this, 'createElement'), $args);
+
+ }
+
+ // }}}
+
+ // {{{ prepElement()
+
+ /**
+ * Make sure all the element array indexes are set
+ *
+ * @param array &$e Element to prep
+ *
+ * @return void
+ * @access protected
+ */
+ protected function prepElement(&$e)
+ {
+ if (!isset($e['opts'])) {
+ $e['opts'] = '';
+ }
+ if (!isset($e['att'])) {
+ $e['att'] = '';
+ }
+ if (!isset($e['val'])) {
+ $e['val'] = '';
+ }
+ if (!isset($e['display'])) {
+ $e['display'] = '';
+ }
+ if (!isset($e['label'])) {
+ $e['label'] = '';
+ }
+ if (!isset($e['noCharLimit'])) {
+ $e['noCharLimit'] = false;
+ }
+ }
+
+ // }}}
+
+ // {{{ registerRules()
+
+ /**
+ * Registers custom form rules you can use when validating
+ *
+ * If the registeredRule token is an array, any QF rule can be
+ * registered. This is useful if you want to register rules
+ * from outside classes
+ * e.g. (Validate, Validate_US, Validate_CA, etc...).
+ *
+ * This will set up a rule called 'checkEmail' which uses the
+ * Validate::email() function.
+ * you can still pass in parameters to this rule if you pass them in
+ * via the 'format' option when you are defining your rules.
+ *
+ * class exampleClass
+ * {
+ * $registeredRules = array(
+ * array(
+ * 'checkEmail',
+ * 'callback',
+ * 'email',
+ * 'Validate'
+ * )
+ * );
+ *
+ * // ... Rest of your class code
+ *
+ * public function configureRules()
+ * {
+ * $r = array();
+ *
+ * $r[] = array(
+ * 'element' => 'process_email',
+ * 'message' => 'ERROR: Invalid email format!',
+ * 'type' => 'checkEmail',
+ * 'format' => array('use_rfc822' => true),
+ * 'validation' => $this->validationType,
+ * 'reset' => false,
+ * 'force' => false
+ * );
+ *
+ * $this->setupRules($r);
+ * }
+ *
+ * // ... Rest of your class code
+ * }
+ *
+ *
+ * If the registeredRule is a string, the corresponding rule in the
+ * glmPEAR/HTML/QuickForm/Rule/ directory will be registered with
+ * the form.
+ *
+ * This will set up the 'phone' rule already defined in the
+ * glmPEAR/HTML/QuickForm/Rule directory which validates both
+ * US and Canadian phone numbers
+ *
+ * class exampleClass
+ * {
+ * $registeredRules = array('phone');
+ *
+ * // ... Rest of your class code
+ *
+ * public function configureRules()
+ * {
+ * $r = array();
+ *
+ * $r[] = array(
+ * 'element' => 'phone',
+ * 'message' => 'ERROR: Invalid number (xxx) xxx-xxxx!',
+ * 'type' => 'phone',
+ * 'format' => null,
+ * 'validation' => $this->validationType,
+ * 'reset' => false,
+ * 'force' => false
+ * );
+ *
+ * $this->setupRules($r);
+ * }
+ *
+ * // ... Rest of your class code
+ * }
+ *
+ *
+ * @return void
+ * @access protected
+ */
+ protected function registerRules()
+ {
+ if (is_array($this->registeredRules)) {
+ foreach ($this->registeredRules as $r) {
+ if (is_array($r)) {
+ call_user_func_array(array(&$this, 'registerRule'), $r);
+ } else {
+ // Don't nedd to register rules more than once
+ if (!$this->isRuleRegistered($r)) {
+ $this->registerRule($r, null, "HTML_QuickForm_Rule_$r");
+ }
+ }
+ }
+ }
+ }
+
+ // }}}
+
+ // {{{ setAutoValidateDateElements()
+
+ /**
+ * Set if we need to auto validate the Date Elements
+ *
+ * @param boolean $validate true/false to auto validate date elements
+ *
+ * @return void
+ * @access public
+ */
+ public function setAutoValidateDateElements($validate)
+ {
+ $this->autoValidateDateElements = $validate;
+ }
+
+ // }}}
+ // {{{ setFormData()
+
+ /**
+ * Sets the submitted values from the form
+ *
+ * Set these values into an internal variable so they will be accessible
+ * anywhere we need them in the form.
+ *
+ * @param array $exclude (optional) Any element names you don't want
+ * included. Since this is primarily used in
+ * emailing, this is helpful to exclude any data
+ * we don't want before the array is generated.
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setFormData(array $exclude = array())
+ {
+ $values = $this->getSubmitValues();
+ foreach ($values as $k => $v) {
+ if ($this->elementExists($k)) {
+ $e =& $this->getElement($k);
+ if (!in_array($e->getName(), $exclude)) {
+ switch ($e->getType()) {
+ case 'date' :
+ list($m, $d, $y) = array_values($e->getValue());
+ // If all the date fields are empty, then don't add
+ // the output to the formData.
+ if (!(empty($m[0]) && empty($d[0]) && empty($y[0]))) {
+ $this->formData[$e->getName()]['label']
+ = $e->getLabel();
+
+ $oldDate = $e->getValue();
+ $newDate = Toolkit_Common::arrayFlatten(
+ $oldDate,
+ 0,
+ $newDate
+ );
+
+ $this->formData[$e->getName()]['element']
+ = implode(' / ', $newDate);
+ unset($oldDate, $newDate);
+ }
+ break;
+
+ case 'group':
+ $e->freeze();
+ $this->formData[$e->getName()]['label'] = $e->getLabel();
+ $this->formData[$e->getName()]['element'] = $e->toHtml();
+ break;
+
+ case 'select' :
+ $this->formData[$e->getName()]['label'] = $e->getLabel();
+
+ $values = $e->getValue();
+ foreach ($values as $v) {
+ $this->formData[$e->getName()]['element'] .= $v;
+ }
+ break;
+
+ default :
+ $this->formData[$e->getName()]['label'] = $e->getLabel();
+ $this->formData[$e->getName()]['element'] = $e->getValue();
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // }}}
+ // {{{ setupConstants()
+
+ /**
+ * Sets the form constant values
+ *
+ * @param array $constants Associative array of form constant values.
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupConstants($constants)
+ {
+ $this->setConstants($constants);
+ }
+
+ // }}}
+ // {{{ setupDefaults()
+
+ /**
+ * Sets the form default values
+ *
+ * @param array $defaults Associative array of form default values.
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupDefaults($defaults)
+ {
+ $this->setDefaults($defaults);
+ }
+
+ // }}}
+ // {{{ setupElements()
+
+ /**
+ * Sets up all the elements to the form
+ *
+ * Takes a multi-dimensional array of form elements and uses them
+ * to set up the form objects elements
+ *
+ * @param array $elements Multi-Dimensional array of form elements.
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupElements($elements)
+ {
+ if (!is_array($elements)) {
+ return;
+ }
+ foreach ($elements as &$e) {
+ $this->prepElement($e);
+ switch ($e['type']) {
+ case 'group' :
+ if (is_array($e['group']) && !empty($e['group'])) {
+ // Special rendering for grouped elements.
+ unset($field);
+ foreach ($e['group'] as $g) {
+ $this->prepElement($g);
+ $field[] =& HTML_QuickForm::createElement(
+ $g['type'],
+ $g['name'],
+ $g['display'],
+ $g['opts'],
+ $g['att'],
+ $g['val']
+ );
+ }
+ $source =& $this->addGroup(
+ $field,
+ $e['name'],
+ $e['label'],
+ $e['seperator'],
+ $e['appendName']
+ );
+ }
+ break;
+
+ case 'elementGrid' :
+ $source =& $this->addElement(
+ $e['type'],
+ $e['name'],
+ $e['display'],
+ $e['opts'],
+ $e['att'],
+ $e['val']
+ );
+ unset($columnNames);
+
+ // Loop through the rows (r) and columns (c)
+ // to add each of the elements to our grid.
+ foreach ($e['group'] as $k => $r) {
+ unset($set, $rowTitle);
+ foreach ($r as $c) {
+ $columnNames[$c['display']] = $c['display'];
+
+ $set[] =& $this->createGridElement(
+ $c['type'],
+ $c['name'],
+ null,
+ $c['opts'],
+ $c['att']
+ );
+ }
+ $rowTitle = is_int($k) ? ' ' : $k;
+ $source->addRow(&$set, $rowTitle);
+ }
+
+ $source->setColumnNames($columnNames);
+ break;
+
+ default :
+ // Render all elements except groups
+ try {
+ $source =& $this->addElement(
+ $e['type'],
+ $e['name'],
+ $e['display'],
+ $e['opts'],
+ $e['att'],
+ $e['val']
+ );
+
+ if (PEAR::isError($source)) {
+ throw new Exception ('PEAR QuickForm Element Error');
+ }
+ } catch (HTML_QuickForm_Error $e) {
+ Toolkit_Common::dieGracefully(null, $e);
+ } catch (Exception $e) {
+ Toolkit_Common::handleError($e);
+ }
+
+ if ($e['type'] == 'advmultiselect') {
+ $source->setLabel($e['labels']);
+ }
+ if ($e['name'] == 'categories') {
+ $res = $source->loadArray($this->categories);
+ if (PEAR::isError($res)) {
+ Toolkit_Common::dieGracefully(null, $res);
+ }
+ }
+ if ($e['type'] == 'header') {
+ $this->formHeaders[$e['display']] = $e;
+ }
+
+ if ($e['name'] == 'captcha_rmv') {
+ $this->captchaAnswer =& $source;
+ }
+
+ if ($e['name'] == 'captcha_question') {
+ $this->captchaQuestion =& $source;
+ }
+ break;
+ }
+ }
+ $this->formElements = $elements;
+ }
+
+ // }}}
+ // {{{ setupFilters()
+
+ /**
+ * Sets any filters needed for the form elements when submitting
+ *
+ * @param array $filters Element filters.
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupFilters($filters)
+ {
+ foreach ($filters as $f) {
+ $res = $this->applyFilter($f['element'], $f['filter']);
+
+ if (PEAR::isError($res)) {
+ Toolkit_Common::handleError($res);
+ }
+ }
+ }
+
+ // }}}
+ // {{{ setupRules()
+
+ /**
+ * Apply rules to the form
+ *
+ * 100 & 1000 char length limitations are automatically assigned to
+ * text/textarea elements to help reduce load limitations on the server.
+ * -request per Chuck in a conference call on (5/22/2009 @ 12:15pm)
+ *
+ * Applies rules that are defined in child classes to the form elements
+ * group rules can be kind of tricky, since you can't apply a rule
+ * directly to an element inside of a rule you have to define
+ * the rule inside a nest of array's and then add a group rule.
+ * the array will contain all the elements inside the group you wish
+ * to apply rules to.
+ *
+ * You can assign as many rules as you would like to individual elements,
+ * and you aren't required to make the array associative, although it is
+ * easier to see whats going on.
+ *
+ * see: http://pear.activeventure.com/package/package.html.html-quickform.html-quickform.addgrouprule.html
+ * for another example.
+ *
+ * // Define the rules for each element in the group.
+ * $num_rule = array(
+ * 'ERROR: Must contain a valid decimal number!',
+ * 'numeric'
+ * );
+ * // Collect together the rules for each element.
+ * $lat_rules = array('lat' => array($num_rule));
+ * $lon_rules = array('lon' => array($num_rule));
+ * $r[] = array(
+ * 'element' => 'latitude',
+ * 'message' => 'ERROR:',
+ * 'type' => 'group',
+ * 'format' => $lat_rules,
+ * 'validation' => $this->validationType,
+ * 'reset' => false,
+ * 'force' => false
+ * );
+ *
+ *
+ * To make a group required but not require every element in the group
+ * you can use the addGroupRule function again
+ * for example: say you have a group of checkboxes and you only only
+ * require 1 be checked. a simple group rule such as the following
+ * will handle this.
+ * N.B. notice the extra "howMany" index.
+ *
+ * $r[] = array(
+ * 'element' => 'element_name',
+ * 'message' => 'ERROR: Error to display!',
+ * 'type' => 'required',
+ * 'format' => null,
+ * 'howMany' => 1,
+ * 'validation'=> $this->validationType,
+ * 'reset' => true,
+ * 'force' => false,
+ * );
+ *
+ *
+ * @param array $rules Multi-Dimensional array of rules for form elements.
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRules(array $rules = null)
+ {
+ $this->registerRules();
+ $preRegisteredRules = $this->getRegisteredRules();
+ if (is_array($this->formElements)) {
+ foreach ($this->formElements as $e) {
+ // Put length limitations on text and textarea fields
+ if ($e['type'] == 'text' && !$e['noCharLimit']) {
+ $this->addCharLimit($e['name'], 100);
+ } elseif ($e['type'] == 'textarea' && !$e['noCharLimit']) {
+ $this->addCharLimit($e['name'], 1000);
+ } elseif ($e['type'] == 'group') {
+ // We need to apply these same limitations to the
+ // text and textarea fields inside of groups
+ $r = array();
+ if (is_array($e['group'])) {
+ foreach ($e['group'] as $i) {
+ // Loop through group elements and if they are
+ // text/textarea fields then put the field into
+ // a rule array that we will assign to the group
+ if ($i['type'] == 'text') {
+ $r[$i['name']][] = array(
+ 'ERROR: 100 characters max!',
+ 'maxlength'
+ );
+ } elseif ($i['type'] == 'textarea') {
+ $r[$i['name']][] = array(
+ 'ERROR: 1000 characters max!',
+ 'maxlength'
+ );
+ }
+ }
+ }
+ if (!empty($r)) {
+ $this->addGroupRule($e['name'], $r);
+ }
+ }
+ if ($this->validationType == 'client') {
+ $label = $e['display'];
+ }
+ if ($e['req']) {
+ if ($e['type'] == 'group') {
+ foreach ($e['group'] as $ge) {
+ if ($ge['req']) {
+ $rule[$ge['name']][] = array(
+ 'ERROR: You must complete this field!',
+ 'required',
+ null,
+ $this->validationType);
+ }
+ }
+ $this->addGroupRule($e['name'], $rule);
+ unset($rule);
+ } elseif ($e['type'] == 'date') {
+ if (!empty($e['error'])) {
+ // Custom error message for the date element.
+ $error = $e['error'];
+ } else {
+ // Default error message for the date element.
+ $error = 'ERROR: You must enter a date!';
+ }
+ $this->addGroupRule(
+ $e['name'],
+ $error,
+ 'required',
+ 3,
+ $this->validationType
+ );
+ if ($this->autoValidateDateElements) {
+ $this->addRule(
+ $e['name'],
+ 'ERROR: Date is invalid!',
+ 'callback',
+ array(&$this, 'checkDateInput')
+ );
+ }
+ } else {
+ $this->addRule(
+ $e['name'],
+ "$label ERROR: You must complete this field!",
+ 'required',
+ null,
+ $this->validationType
+ );
+ }
+ }
+ }
+ }
+ if (is_array($rules)) {
+ foreach ($rules as $r) {
+ if (!is_array($r['element'])) {
+ $group = ($this->getElementType($r['element']) == 'group');
+ }
+ if ($group) {
+ $this->addGroupRule(
+ $r['element'],
+ $r['message'],
+ $r['type'],
+ $r['format'],
+ $r['howMany'],
+ $r['validation'],
+ $r['reset']
+ );
+ } elseif (in_array($r['type'], $preRegisteredRules)) {
+ $this->addRule(
+ $r['element'],
+ $r['message'],
+ $r['type'],
+ $r['format'],
+ $r['validation'],
+ $r['reset'],
+ $r['force']
+ );
+ }
+ }
+ }
+ }
+
+ // }}}
+ // {{{ setupRenderers()
+
+ /**
+ * Sets up renderers for form objects
+ *
+ * Uses the default form renderer to allow templates to be injected
+ * into the form object before displaying on a page. This allows
+ * changing the face of the form w/ out any backend adjustment.
+ *
+ * Files that can be created for templates are
+ *
+ * Examples:
+ * # Element.tpl
+ *
+ *
';
+ return false;
+ exit;
+ }
+ return $StoredName;
+ }
+ }
+
+ // }}}
+
+ // {{{ getImageSize()
+
+ /**
+ * getImageSize
+ *
+ * Return image data on an image from image server
+ *
+ * @param string $image Full URI to image
+ * http://is0/userId/imageStyle/imageName
+ * Must be a full URI including an authority.
+ * No relative URIs, the // are mandatory
+ *
+ * @return array Image data 0 => width, 1 => height, 2 => html
+ * @access public
+ * @throws PEAR Error
+ */
+ function getImageSize($image)
+ {
+ $options = array('allowed_schemes' => array('http'));
+ if (!Validate::uri($image, $options)) {
+ return PEAR::raiseError('Invalid URI for the image');
+ }
+
+ $ch = curl_init();
+ $curlOptions = array(
+ CURLOPT_URL => "{$image}/info",
+ CURLOPT_HEADER => 0,
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_POSTFIELDS => $fileData
+ );
+ curl_setopt_array($ch, $curlOptions);
+
+ $response = curl_exec($ch);
+ curl_close($ch);
+ $wPattern = "/(.*)<\/width>/";
+ preg_match($wPattern, $response, $matches);
+ $width = $matches[1];
+ $hPattern = "/(.*)<\/height>/";
+ preg_match($hPattern, $response, $matches);
+ $height = $matches[1];
+ $html = "width=\"{$width}\" height=\"{$height}\"";
+ return array($width, $height, $html);
+ }
+
+ // }}}
+
+ // {{{ xmlPathContent()
+
+ /**
+ * xmlPathContent
+ *
+ * Grab the content given XPath Query
+ *
+ * @param unknown $dom DOMDocument nodelist
+ * @param unknown $content query for XPath
+ *
+ * @return object string of node
+ * @access public
+ */
+ function xmlPathContent($dom, $content)
+ {
+ $xPath = new DOMXPath($dom);
+ $nodelist = $xPath->query($content);
+ foreach ($nodelist as $entry) {
+ return $entry->nodeValue;
+ }
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Logger.php b/Toolkit/Logger.php
new file mode 100644
index 0000000..a5835c4
--- /dev/null
+++ b/Toolkit/Logger.php
@@ -0,0 +1,168 @@
+
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version CVS: $Id: Logger.php,v 1.1 2012/02/03 19:04:26 matrix Exp $
+ * @link <>
+ * @see Log
+ */
+
+/**
+ * Logging class used to handle system logs
+ */
+require_once 'Log.php';
+
+/**
+ * Error handling logger for system
+ *
+ * @category Logger
+ * @package Toolkit_Logger
+ * @author Jamie Kahgee
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version Release: @package_version@
+ * @link <>
+ * @see Log
+ */
+class Toolkit_Logger
+{
+ // {{{ &getLogger()
+
+ /**
+ * Gets a concrete log subclass based on constant parameters set for server
+ *
+ * Define parameters in server setup block of bootstrap file
+ *
+ * @return Log concrete Log subclass
+ * @access public
+ * @static
+ */
+ public static function &getLogger()
+ {
+ if (defined('ERROR_LOG_NAME') && constant('ERROR_LOG_NAME') != '') {
+ $errorLogName = constant('ERROR_LOG_NAME');
+ } else {
+ $errorLogName = '';
+ }
+
+ $logger =& Log::singleton(
+ ERROR_LOG_TYPE,
+ $errorLogName,
+ constant('ERROR_LOG_IDENT'),
+ $GLOBALS['ERROR_LOG_CONF'],
+ constant('ERROR_LOG_LEVEL')
+ );
+
+ return $logger;
+ }
+
+ // }}}
+ // {{{ errorHandler()
+
+ /**
+ * User-defined error handler function
+ *
+ * handles errors in script. E_ERROR, E_WARNING, E_NOTICE are automatically
+ * logged when they occur. Fatal errors (E_ERROR) have a 404 page shown to
+ * user so script doesn't halt.
+ *
+ * @param int $errno Level of the error rasied
+ * @param string $errstr Error message
+ * @param string $errfile Filename that the error was raised in
+ * @param int $errline Line number the error was raised at
+ * @param Log $logger Logger to user for error loggin
+ *
+ * @return boolean false, allows the normal error handler to continue
+ * @access public
+ * @static
+ */
+ public static function errorHandler(
+ $errno,
+ $errstr,
+ $errfile,
+ $errline,
+ $logger = null
+ ) {
+ if (!($logger instanceof Log)) {
+ $logger =& self::getLogger();
+ }
+
+ $msg = "$errstr in $errfile at line $errline";
+ switch ($errno) {
+ case E_ERROR :
+ case E_USER_ERROR :
+ $logger->emerg($msg, PEAR_LOG_EMERG);
+ header("HTTP/1.0 404 Not Found");
+ exit(1);
+ break;
+
+ case E_WARNING :
+ CASE E_USER_WARNING :
+ $logger->warning($msg, PEAR_LOG_WARNING);
+ break;
+
+ case E_NOTICE :
+ case E_USER_NOTICE :
+ $logger->notice($msg, PEAR_LOG_NOTICE);
+ break;
+
+ default :
+ $logger->info($msg, PEAR_LOG_INFO);
+ break;
+ }
+
+ return false; // let the normal error handler continue
+ }
+
+ // }}}
+ // {{{ logException()
+
+ /**
+ * Create a log for an exception
+ *
+ * @param string $type Type of error encountered that caused exception
+ * @param Exception $e Exception that was thrown
+ *
+ * @return void
+ * @static
+ */
+ public static function logException($type, Exception $e)
+ {
+ $msg = $e->getMessage();
+ $file = $e->getFile();
+ $line = $e->getLine();
+
+ $lcType = strtolower($type); // uniformity in type when looking at log
+ $log = "[$lcType] $msg in $file at line $line";
+
+ $logger =& self::getLogger();
+
+ switch ($lcType) {
+ case 'db error' :
+ case 'invalid arg' :
+ case 'runtime error' :
+ $logger->emerg($log);
+ break;
+
+ case 'image server' :
+ case 'file server' :
+ $logger->warning($log);
+ break;
+
+ default :
+ $logger->err($log);
+ break;
+ }
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members.php b/Toolkit/Members.php
new file mode 100644
index 0000000..5ef8da4
--- /dev/null
+++ b/Toolkit/Members.php
@@ -0,0 +1,281 @@
+
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: Members.php,v 1.2 2009/12/15 20:18:15 jamie Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Base class for the memberdb
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Members
+{
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * @access public
+ */
+ public function __construct()
+ {
+ HTTP_Session2::useCookies(false);
+ HTTP_Session2::start('MemberDB');
+ if (HTTP_Session2::get('newSearch')) {
+ HTTP_Session2::set('newSearch', false);
+ HTTP_Session2::set('searchResults', $_SERVER['HTTP_REFERER']);
+ }
+ }
+
+ // }}}
+
+ // {{{ toHtml()
+
+ /**
+ * Determine which form to show to the user
+ *
+ * When editing a member the (a)ction in the URL controls
+ * which form is displayed to the user. Member Id's from
+ * the database should be passed along as the ID in the $_GET array.
+ *
+ * @return void
+ * @access public
+ */
+ public function toHtml()
+ {
+ $pdo = Toolkit_Database::getInstance();
+ // application configuration
+ $conf = new Config;
+ $root =& $conf->parseConfig(BASE . 'Toolkit/Members/members.ini', 'IniFile');
+
+ $nav =& new Toolkit_Members_RecordNavigation($root);
+ $nav->setupAdminNavStructure();
+
+ $tplOpts = Toolkit_Members::getFlexyOptions();
+ $tEngine = new HTML_Template_Flexy($tplOpts);
+
+ switch ($_GET['tab']) {
+ case 6 :
+ $mc =& new Toolkit_Members_EditMemberContacts(
+ Toolkit_Database::getInstance(),
+ 'edit_contacts',
+ 'post',
+ null,
+ null,
+ null,
+ true
+ );
+ if ($_GET['d'] == 't' && is_numeric($_GET['cid'])) {
+ $mc->removeContact($_GET['cid'], $_GET['id']);
+ }
+ $mc->setConfig($root);
+ $mc->configureForm();
+ $out = $mc->toHtml();
+ break;
+
+ case 5 :
+ $mf =& new Toolkit_Members_EditMemberFile(
+ $pdo,
+ 'edit_files'
+ );
+ $mf->setConfig($root);
+ $mf->configureForm();
+ $out = $mf->toHtml();
+ break;
+
+ case 4 :
+ $ma =& new Toolkit_Members_EditMemberAmenities(
+ $pdo,
+ 'edit_amenities',
+ 'post',
+ null,
+ null,
+ null,
+ true
+ );
+ $ma->setConfig($root);
+ $ma->configureForm();
+ $out = $ma->toHtml();
+ break;
+
+ case 3 :
+ $mp = new Toolkit_Members_Admin_EditPackages(
+ $pdo,
+ $tEngine
+ );
+ $mp->setupPage();
+ $out = $mp->getPage($nav);
+ break;
+
+ case 2 :
+ // Object to use when rendering the page template
+ $page = new stdClass();
+ // Page navigation
+ $page->nav = $nav->getPageNav();
+
+ // Linked List of member photos
+ $linkedList = new Toolkit_Members_Photos(null, $_GET['id']);
+ $linkedList->createMemberList(
+ $pdo,
+ $root
+ );
+ // Member Object to get calculate attributes about a member
+ $member = new Toolkit_Members_Member(
+ $pdo,
+ $root
+ );
+ // Server side caching
+ $cache = new Cache_Lite(Toolkit_Members::getCacheOptions());
+ // Image server for processing uploaded images
+ $is = new Toolkit_Image_Server();
+
+ if ($member->canAddPhotos($linkedList, $root)) {
+ $aForm = new Toolkit_Members_Admin_AddPhoto(
+ $pdo,
+ 'new_member_photo',
+ 'post',
+ BASE_URL . "admin/members.php?cat=2&subCat=2&tab=2&id={$_GET['id']}",
+ '',
+ null,
+ true
+ );
+ $aForm->configureForm($root);
+ $page->uploadForm = $aForm->toHtml(
+ $tEngine,
+ $cache,
+ $root,
+ $is,
+ $linkedList
+ );
+ }
+
+ if ($member->hasUploadedPhotos($linkedList)) {
+ $editForms = array();
+ $linkedList->rewind();
+
+ foreach ($linkedList as $i) {
+ if (!$i->getPending()) {
+ $id = $i->getId();
+ $eForm = new Toolkit_Members_Admin_EditPhoto(
+ $pdo,
+ $linkedList,
+ "edit_member_photo_$id",
+ 'post',
+ BASE_URL . "admin/members.php?cat=2&subCat=2&tab=2&id={$_GET['id']}",
+ '',
+ array('id' => $id),
+ true
+ );
+ $eForm->configureForm($root);
+ $page->editForms[$id] = $eForm->toHtml(
+ $tEngine,
+ $cache,
+ $is,
+ $root
+ );
+ }
+ }
+ }
+
+ // get reference to [photos] section of config file
+ $config =& $root->getItem('section', 'photos');
+ $template =& $config->getItem('directive', 'editGalleryTemplate');
+
+ $tEngine->compile($template->getContent());
+ $out = $tEngine->bufferedOutputObject($page);
+ break;
+
+ case 1 :
+ default :
+ $mr =& new Toolkit_Members_EditMemberInfo(
+ $pdo,
+ 'edit_member',
+ 'post',
+ null,
+ null,
+ null,
+ true
+ );
+
+ $mr->setStates(
+ Toolkit_Common::getStates($pdo)
+ );
+ $mr->setConfig($root);
+ $mr->configureForm();
+ $out = $mr->toHtml();
+ break;
+ }
+
+ return $out;
+ }
+
+ // }}}
+
+ // {{{ getCacheOptions()
+
+ /**
+ * Get the cache options defined for the memberdb app
+ *
+ * @return array Cache_Lite options defined for the memberdb app
+ * @access public
+ * @static
+ */
+ public static function getCacheOptions()
+ {
+ $options = $GLOBALS['cacheOptions'];
+ $options['cacheDir'] = BASE . 'Toolkit/Members/cache/';
+ return $options;
+ }
+
+ // }}}
+ // {{{ getFlexyOptions()
+
+ /**
+ * Get the flexy options defined for the memberdb app
+ *
+ * @return array Flexy template options defined for the memberdb app
+ * @access public
+ * @static
+ */
+ public static function getFlexyOptions()
+ {
+ $options = $GLOBALS['flexyOptions'];
+ $options['templateDir'] = BASE . 'Toolkit/Members/templates/';
+ $options['compileDir'] = BASE . 'Toolkit/Members/templates/compiled/';
+ return $options;
+ }
+
+ // }}}
+
+ // {{{ show()
+
+ /**
+ * Show the page
+ *
+ * @return void
+ * @access public
+ */
+ public function show()
+ {
+ echo $this->toHtml();
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/AddPhoto.php b/Toolkit/Members/AddPhoto.php
new file mode 100644
index 0000000..0316124
--- /dev/null
+++ b/Toolkit/Members/AddPhoto.php
@@ -0,0 +1,198 @@
+
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: AddPhoto.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit/Image/Server.php
+ */
+
+
+/**
+ * The image server processing class
+ */
+require_once BASE . 'Toolkit/Image/Server.php';
+
+/**
+ * Form to handle creating a new photo in the members only area
+ *
+ * Handles inserting new photo into db as a pending photo and creating a
+ * tuple in the member_updates table which will allow the admin to
+ * approve/deny the new photo request.
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Members_AddPhoto extends Toolkit_Members_Admin_AddPhoto
+{
+ // {{{ createPendingPhoto()
+
+ /**
+ * Adds photo to member and makes a pending row in the updates table
+ *
+ * Adds a photo to the member_photos table but sets the pending field
+ * to true and then inserts a row into the updates table to make the field
+ * pending. If the photo gets rejected we will have to delete from both
+ * the updates table and the member_photos table.
+ *
+ * @param array &$values submitted values from the form.
+ *
+ * @return boolean Result of creating a pending photo
+ * @access protected
+ */
+ protected function createPendingPhoto(&$values)
+ {
+ try {
+ // Get the last photo inserted.
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE pending = true
+ AND member_id = :member_id
+ ORDER BY id DESC";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(
+ ':member_id',
+ $GLOBALS['memberAuth']->getAuthData('member_id'),
+ PDO::PARAM_INT
+ );
+ $stmt->execute();
+ $photo = $stmt->fetch();
+
+ // Insert the picture into the updates table for approval.
+ $label = '';
+ $update = false;
+ $dataType = 'boolean';
+ $field = 'pending';
+
+ $sql = "
+ INSERT INTO " . Toolkit_Membersonly::PENDING_TABLE . "
+ (member_id, field, update , db_table,
+ data_type, label, foreign_key)
+ VALUES (:member_id, :field, :update, :db_table,
+ :data_type, :label, :foreign_key)";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(
+ ':member_id',
+ $GLOBALS['memberAuth']->getAuthData('member_id'),
+ PDO::PARAM_INT
+ );
+ $stmt->bindParam(':field', $field, PDO::PARAM_STR);
+ $stmt->bindParam(':update', $update, PDO::PARAM_BOOL);
+ $stmt->bindParam(':db_table', $this->tableName, PDO::PARAM_STR);
+ $stmt->bindParam(':data_type', $dataType, PDO::PARAM_STR);
+ $stmt->bindParam(':label', $label, PDO::PARAM_STR);
+ $stmt->bindParam(':foreign_key', $photo['id'], PDO::PARAM_STR);
+ return $stmt->execute();
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ processData()
+
+ /**
+ * Handles setting up the from processing and which function to get it done
+ *
+ * @param array $values Submitted values from the form.
+ *
+ * @return void
+ * @access protected
+ */
+ protected function processData($values)
+ {
+ try {
+ $this->dbh->beginTransaction();
+ $sql = Toolkit_Common::createSQLInsert(
+ $this->tableName,
+ array_keys($values)
+ );
+
+ $res = Toolkit_Common::processQuery($this->dbh, $sql, $values);
+
+
+ if ($values['pending']) {
+ $this->createPendingPhoto($values);
+ }
+ $this->dbh->commit();
+ } catch (PDOException $e) {
+ $this->dbh->rollBack();
+ return Toolkit_Common::handleError($e);
+ }
+
+ header('Location:' . $this->getAttribute('action'));
+ }
+
+ // }}}
+
+ // {{{ toHtml()
+
+ /**
+ * Renders the form
+ *
+ * sets the page the form should be redirected to instead of coming back
+ * around to itself.
+ *
+ * @param HTML_Template_Flexy $tEngine Templating Engine
+ * @param Cache_Lite $cache Caching Engine
+ * @param Config_Container $c Application configuration
+ * @param Toolkit_Image_Server $is Image Server
+ * @param Toolkit_Members_Photos $ll Linked List of member photos
+ *
+ * @return string The rendered form
+ * @access public
+ */
+ public function toHtml(
+ HTML_Template_Flexy $tEngine,
+ Cache_Lite $cache,
+ Config_Container $c,
+ Toolkit_Image_Server $is,
+ Toolkit_Members_Photos $ll
+ ) {
+ if ($this->validate()) {
+ $config = $c->getItem('section', 'conf');
+ $strictPending = $config->getItem('directive', 'strictPending');
+
+ $id = $GLOBALS['memberAuth']->getAuthData('member_id');
+ $cache->remove("Member-$id", 'Profile');
+
+ // Inject some data into the submitted values
+ $this->_submitValues['image'] = $is->imageUpload('file');
+ $this->_submitValues['pos'] = $ll->getListSize() + 1;
+ $this->_submitValues['member_id'] = $id;
+ $this->_submitValues['pending'] = (int) $strictPending->getContent();
+
+ unset($this->_submitValues['MAX_FILE_SIZE'],
+ $this->_submitValues['submit']);
+
+ $this->process(array(&$this, 'processData'), false);
+ }
+
+ $this->setupRenderers($tEngine);
+
+ return $tEngine->bufferedOutputObject($this->view);
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/AddYourBusiness.php b/Toolkit/Members/AddYourBusiness.php
new file mode 100755
index 0000000..543812b
--- /dev/null
+++ b/Toolkit/Members/AddYourBusiness.php
@@ -0,0 +1,1246 @@
+
+ * @copyright 2008 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: AddYourBusiness.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+require_once 'FormBuilder.php';
+
+/**
+ * Description for require_once
+ */
+require_once 'Members/CategoryTree.php';
+
+/**
+ * Creates, Renders, Processes form for request to be added to Business DB
+ *
+ * This Form just sends the primary advisee an HTML email of the data
+ * that was filled in and requires them to add the users to the Business DB
+ * themselves.
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2008 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Members_AddYourBusiness
+ extends Toolkit_FormBuilder implements Toolkit_Form
+{
+ // {{{ properties
+
+ /**
+ * PDO connections
+ *
+ * @var string
+ * @access public
+ */
+ public $dbh;
+
+ /**
+ * Allow duplicate member names to be valid or not
+ *
+ * @var boolean
+ * @access private
+ */
+ private $_preventDupNames;
+
+ /**
+ * The name of the DB table that holds the member records
+ *
+ * @var array
+ * @access protected
+ */
+ public $tableName = 'member';
+
+ /**
+ * What do you want the success msg to be if the form validates successfully
+ *
+ * @var string
+ * @access protected
+ */
+ protected $successMsg = '
+
+ Your business Information has been successfully submitted.
+ A representative will be contacting you shortly to follow up.
+
';
+
+ /**
+ * Primary email address to send notification a record has been updated
+ *
+ * Set this value to false and it will turn off the email
+ * update notifications.
+ *
+ * @var string
+ * @access protected
+ */
+ protected $primaryAdvisee;
+
+ /**
+ * Email address of people that might also want to be advised of updates
+ *
+ * A list of all email address that might also want to be advised
+ * updates have been made on a business record. You can add as many
+ * as you would like and they will be CC in the email.
+ *
+ * If you use associative key values then they will be appended
+ * to the email string. i.e.
+ * Jamie Kahgee
+ * Other wise the address will just be added.
+ *
+ * N.B. You cannot make this array bigger than 5 people or you will need to
+ * rewrite the function to handle the server spam issue.
+ *
+ * @var array
+ * @access private
+ */
+ protected $secondaryAdvisees = array(
+ );
+
+ /**
+ * If the admin needs to approve members before they are allowed to join
+ *
+ * @var boolean
+ * @access protected
+ * @see $authNetAccount
+ */
+ protected $approvalNeeded = true;
+
+ /**
+ * Should the captcha be included in the form
+ *
+ * If credit card processing is being handled in the form there is usually
+ * no need to include the captcha.
+ * Setting this value to false will cause the captcha to be excluded
+ *
+ * @var boolean
+ * @access protected
+ * @see $authNetAccount
+ */
+ protected $includeCaptcha = false;
+
+ /**
+ * If new members will use auth.net to pay and create a new account
+ *
+ * This will override the approvalNeeded property, as a paid member
+ * account should not need to have thier account authorized twice.
+ *
+ *
+ * protected $autNetAccount = array(
+ * 'auth_net_login_id' => '1234key',
+ * 'auth_net_tran_key' => '1234567890key',
+ * );
+ *
+ *
+ * @var boolean
+ * @access protected
+ */
+ protected $authNetAccount = false;
+
+ /**
+ * Flexy options used in the renderer
+ *
+ * @var array
+ * @access protected
+ */
+ protected $flexyOptions;
+
+ /**
+ * The default rules to register for validating
+ *
+ * @var array
+ * @access protected
+ */
+ protected $registeredRules = array();
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * @param PDO $pdo PHP Data Object to use for DB calls
+ * @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
+ * @see Toolkit_FormBuilder, HTML_QuickForm
+ */
+ public function __construct(
+ PDO $pdo,
+ $formName,
+ $method = 'post',
+ $action = '',
+ $target = '',
+ $attributes = null,
+ $trackSubmit = false
+ ) {
+ parent::__construct(
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+ $this->template = dirname(__FILE__) . '/templates/currentTables/';
+
+ $this->dbh = $pdo;
+ if (!$this->approvalNeeded && is_array($this->authNetAccount)) {
+ $this->approvalNeeded = false;
+ }
+
+ if ($this->primaryAdvisee !== false && empty($this->primaryAdvisee)) {
+ // Set to false to turn off email function.
+ $this->primaryAdvisee = OWNER_EMAIL;
+ }
+
+ $this->flexyOptions = Toolkit_Members::getFlexyOptions();
+ $var = basename(__FILE__, '.php');
+
+ $callbackUrl = ($_SERVER['HTTPS'] == 'on') ?
+ BASE_SECURE_URL : 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,
+ ),
+ );
+ }
+
+ // }}}
+
+ // {{{ checkCvv()
+
+ /**
+ * Check if the credit card CVV is properly formatted
+ *
+ * @param array $values credit card num and cvv number from the form
+ *
+ * @return boolean whether the cvv is properly formatted
+ * @access public
+ */
+ public function checkCvv($values)
+ {
+ return Validate_Finance_CreditCard::cvv($values[0], $values[1]);
+ }
+
+ // }}}
+ // {{{ checkDateInput()
+
+ /**
+ * Checks the validation of a m-d-Y date
+ *
+ * This function will only be called if the autoValidateDateElements
+ * property is set to true
+ *
+ * @param array $value Date element from form.
+ *
+ * @return boolean
+ * @access public
+ * @see Toolkit_FormBuilder::autoValidateDateElements
+ */
+ public function checkDateInput($value)
+ {
+ $res1 = is_numeric($value['m']);
+ $res2 = is_numeric($value['Y']);
+
+ if (!($res1 && $res2)) {
+ return false;
+ }
+
+ $date = implode('-', $value);
+
+ return Validate::date($date, array('format' => '%j-%Y'));
+ }
+
+ // }}}
+ // {{{ checkMemberLogin()
+
+ /**
+ * Check to see if the member name is valid (doesn't already exists)
+ *
+ * @param string $uname desired user name to check
+ *
+ * @return boolean if the username is valid (doesn't exist)
+ * @access public
+ */
+ public function checkMemberLogin($uname)
+ {
+ try {
+ $sql = "
+ SELECT count(*) AS total
+ FROM {$this->tableName}
+ WHERE member_login = :uname";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':uname', $uname, PDO::PARAM_STR);
+ $stmt->execute();
+ $stmt->bindColumn('total', $isValid);
+ $stmt->fetch();
+
+ return (bool) !$isValid;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ checkMemberName()
+
+ /**
+ * Checks for duplicate member names
+ *
+ * @param string $name Member name to check for
+ *
+ * @return boolean if the name is valid (doesn't exist)
+ * @access public
+ */
+ public function checkMemberName($name)
+ {
+ try {
+ $sql = "
+ SELECT count(*) AS total
+ FROM {$this->tableName}
+ WHERE member_name = :name";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':name', $name, PDO::PARAM_STR);
+ $stmt->execute();
+ $stmt->bindColumn('total', $isValid);
+ $stmt->fetch();
+
+ return (bool) !$isValid;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ checkNumber()
+
+ /**
+ * Check if the credit card number is properly formatted
+ *
+ * Credit card numbers have a specific formatting based on the credit card
+ * types.
+ * i.e. (visa, discover, etc...) This call verifies if the # was properly
+ * formatted against the card type selected
+ *
+ * @param array $values credit card type and number from the form
+ *
+ * @return boolean if cc number is properly formatted based on the card type
+ * @access public
+ */
+ public function checkNumber($values)
+ {
+ if (empty($values[1])) {
+ $values[1] = null;
+ }
+
+ return Validate_Finance_CreditCard::number($values[0], $values[1]);
+ }
+
+ // }}}
+ // {{{ configureConstants()
+
+ /**
+ * Sets the constants for the form
+ *
+ * @return void
+ * @access public
+ */
+ public function configureConstants()
+ {
+ if ($this->approvalNeeded || !is_array($this->authNetAccount)) {
+ $newMember = 1;
+ } else {
+ $newMember = 0;
+ }
+ $constants = array(
+ 'new_member' => $newMember,
+ );
+
+ $this->setupConstants($constants);
+ }
+
+ // }}}
+ // {{{ configureElements()
+
+ /**
+ * Setup the elements to use on the form.
+ *
+ * @return void
+ * @access public
+ */
+ public function configureElements()
+ {
+ $e = array();
+ // get reference to [listing type] section of config file
+ $config =& $this->config->getItem('section', 'listing type');
+ // get coupon
+ $singularDirective =& $config->getItem('directive', 'singular');
+ $singularType = $singularDirective->getContent();
+ $pluralDirective =& $config->getItem('directive', 'plural');
+ $pluralType = $pluralDirective->getContent();
+
+ $this->setCategories();
+ // All Grouped Elements are created here.
+
+ // All Elements are created here. This includes group element definitions.
+ // Member Information
+ $e[] = array(
+ 'type' => 'hidden',
+ 'req' => false,
+ 'name' => 'new_member'
+ );
+ $e[] = array(
+ 'type' => 'header',
+ 'req' => false,
+ 'name' => 'yourInfoHdr',
+ 'display' => 'Your Information'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'fname',
+ 'display' => 'First Name'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'lname',
+ 'display' => 'Last Name'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'member_contact_email',
+ 'display' => 'Email'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'member_contact_email_rmv',
+ 'display' => 'Confirm Email'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'phone',
+ 'display' => 'Phone'
+ );
+ $e[] = array(
+ 'type' => 'header',
+ 'req' => false,
+ 'name' => 'businessInfoHdr',
+ 'display' => "$singularType Information",
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'member_name',
+ 'display' => "$singularType Name",
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'member_login',
+ 'display' => 'Username'
+ );
+ $e[] = array(
+ 'type' => 'password',
+ 'req' => true,
+ 'name' => 'member_passwd',
+ 'display' => 'Password'
+ );
+ $e[] = array(
+ 'type' => 'password',
+ 'req' => true,
+ 'name' => 'member_passwd_rmv',
+ 'display' => 'Confirm Password'
+ );
+ $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()
+
+ /**
+ * Setup the filters to apply to the elements before we are
+ * handed the values submitted
+ *
+ * @return void
+ * @access public
+ */
+ public function configureFilters()
+ {
+ $f = array();
+ $f[] = array(
+ 'element' => '__ALL__',
+ 'filter' => 'trim'
+ );
+
+ $this->setupFilters($f);
+ }
+
+ // }}}
+ // {{{ configureForm()
+
+ /**
+ * Helper method to setup the entire form
+ *
+ * @return void
+ * @access public
+ */
+ public function configureForm()
+ {
+ $this->configureElements();
+ $this->configureRules();
+ $this->configureFilters();
+ $this->configureConstants();
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Sets up all the rules to be used when the form is validated.
+ *
+ * @return void
+ * @access public
+ */
+ public function configureRules()
+ {
+ $r = array();
+ $r[] = array(
+ 'element' => 'member_contact_email',
+ 'message' => 'ERROR: Invalid email address!',
+ 'type' => 'email',
+ 'format' => null,
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => array(
+ 'member_contact_email',
+ 'member_contact_email_rmv'
+ ),
+ 'message' => 'ERROR: Your email addresses do not match!',
+ 'type' => 'compare',
+ 'format' => null,
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => array(
+ 'member_passwd',
+ 'member_passwd_rmv'
+ ),
+ 'message' => 'ERROR: Your passwords do not match!',
+ 'type' => 'compare',
+ 'format' => null,
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ if ($this->_preventDupNames) {
+ $r[] = array(
+ 'element' => 'member_name',
+ 'message' => 'ERROR: This name already exists!',
+ 'type' => 'callback',
+ 'format' => array(&$this, 'checkMemberName'),
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ }
+ $r[] = array(
+ 'element' => 'member_login',
+ 'message' => 'ERROR: This username is taken already!',
+ 'type' => 'callback',
+ 'format' => array(&$this, 'checkMemberLogin'),
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ if (is_array($this->authNetAccount)) {
+ $r[] = array(
+ 'element' => array('cc_num', 'cc_type'),
+ 'message' => 'ERROR: Number does not match card type!',
+ 'type' => 'callback',
+ 'format' => array(&$this, 'checkNumber'),
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => array('cc_cvv', 'cc_type'),
+ 'message' => 'ERROR: CVV does not match card type!',
+ 'type' => 'callback',
+ 'format' => array(&$this, 'checkCvv'),
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ }
+ if ($this->includeCaptcha) {
+ $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);
+ }
+
+ // }}}
+ // {{{ createCategories()
+
+ /**
+ * Creates an array from the array of category tree objects
+ *
+ * @param array $tree linear category tree array
+ * @param integer $depth what level we are on
+ *
+ * @return array The array list of categories that
+ * that can be loaded into a select element
+ * @access protected
+ */
+ protected function createCategories($tree, $depth = 0)
+ {
+ $this->records[] = $tree->category;
+ if ($depth == 0) {
+ $this->categories[$tree->catid] = "{$tree->category}";
+ } else {
+ $this->categories[$tree->catid] = $tree->category;
+ }
+ if (empty($tree->children)) {
+ return;
+ } else {
+ ++$depth;
+ foreach ($tree->children as $miniTrees) {
+ $this->createCategories($miniTrees, $depth);
+ }
+ }
+ }
+
+ // }}}
+
+ // {{{ getCategories()
+
+ /**
+ * Creates array structure of the category tree for use in a select element.
+ *
+ * This method will also instantiate a class property called tree for your
+ * class. This object will hold the tree structure of the categories list
+ * from the Database.
+ *
+ * @return array The array list of categories that can be loaded
+ * into a select element
+ *
+ * @access protected
+ */
+ protected function getCategories()
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM category
+ WHERE parent_id = 0
+ ORDER BY name";
+ foreach ($this->dbh->query($sql) as $row) {
+ $this->tree[] = new Toolkit_Members_CategoryTree($row['category_id'], $row['name'], $this->dbh);
+ }
+ if (!empty($this->tree)) {
+ foreach ($this->tree as $t) {
+ $this->createCategories($t);
+ }
+ }
+
+ if (empty($this->categories)) {
+ $this->categories = array('' => '-- No Categories Created Yet --');
+ } else {
+ $this->categories
+ = array('' => '-- Select Category --') + $this->categories;
+ }
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ 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)
+ {
+ try {
+ // If they are paying via auth.net and their account
+ // doesn't go through, then don't actually insert the member.
+ if (is_array($this->authNetAccount)) {
+ if (!$this->processAuthNet()) {
+ return false;
+ }
+ }
+
+ $this->dbh->beginTransaction();
+ $memberCategory = $values['category_id'];
+ unset($values['category_id']);
+ $params = implode(', ', array_keys($values));
+ $bindParams = ':' . implode(', :', array_keys($values));
+
+ $sql = "
+ INSERT INTO {$this->tableName} ($params)
+ VALUES ($bindParams)";
+ $stmt = $this->dbh->prepare($sql);
+ foreach ($values as $k => &$v) {
+ $metaData = $this->tableMetaData[$k];
+ if ($metaData == 'integer') {
+ $dataType = PDO::PARAM_INT;
+ } elseif ($metaData == 'boolean') {
+ $dataType = PDO::PARAM_BOOL;
+ } else {
+ $dataType = PDO::PARAM_STR;
+ }
+ // For empty values that are not actually a zero (0), we
+ // want to insert null's.
+ if (empty($v) && $v !== 0) {
+ $v = null;
+ $dataType = PDO::PARAM_NULL;
+ }
+ $stmt->bindParam(":$k", $v, $dataType);
+ }
+ $stmt->execute();
+
+ $sql = "
+ SELECT member_id
+ FROM {$this->tableName}
+ ORDER BY member_id DESC LIMIT 1";
+
+ $row = $this->dbh->query($sql)->fetch();
+
+ $sql = "
+ INSERT INTO member_category (member_id, category_id)
+ VALUES (:mid, :cid)";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':mid', $row['member_id']);
+ $stmt->bindParam(':cid', $memberCategory, PDO::PARAM_INT);
+ $stmt->execute();
+
+ // If they are paying via auth.net and their account
+ // doesn't go through, then don't actually insert the member.
+ if (is_array($this->authNetAccount)) {
+ $res = $this->processAuthNet($authValues);
+ if (is_array($res) && !empty($res)) {
+ if ($res[0] == 1) {
+ // CC was Accepted.
+ $this->dbh->commit();
+ return true;
+ } elseif ($res[0] == 2) {
+ // CC was Declined.
+ $this->dbh->rollback();
+ return 2;
+ } else {
+ // There was a CC processing error.
+ $this->dbh->rollback();
+ return $res[0];
+ }
+ } else {
+ // There was a CC processing error.
+ $this->dbh->rollback();
+ return false;
+ }
+ } else {
+ // Not paying by CC so just commit the insert.
+ return $this->dbh->commit();
+ }
+ } catch (PDOException $e) {
+ $this->dbh->rollback();
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ processAuthNet()
+
+ /**
+ * Send payment to auth.net
+ *
+ * Test Cards
+ * Card Number Card Type
+ * =============== ===============
+ * 370000000000002 American Express
+ * 6011000000000012 Discover Card
+ * 5424000000000015 MasterCard
+ * 4000000000000000 Visa
+ *
+ * @param array $values Submitted values from the form
+ *
+ * @return array Auth.net response
+ * @access protected
+ */
+ protected function processAuthNet($values)
+ {
+ $this->setFormData();
+ $authNetLoginId = $this->authNetAccount['auth_net_login_id'];
+ $authNetTranKey = $this->authNetAccount['auth_net_tran_key'];
+ $authNetUrl = "https://secure.authorize.net/gateway/transact.dll";
+
+ $authNetValues = array(
+ 'x_login' => $authNetLoginId,
+ 'x_version' => '3.1',
+ 'x_delim_char' => '|',
+ 'x_delim_data' => 'TRUE',
+ 'x_type' => 'AUTH_CAPTURE',
+ 'x_method' => 'CC',
+ 'x_tran_key' => $authNetTranKey,
+ 'x_relay_response' => 'FALSE',
+ 'x_card_num' => $values['cc_num'],
+ 'x_exp_date' => implode('', $values['cc_exp']),
+ 'x_amount' => $values[$values['member_type']],
+ 'x_first_name' => $values['cc_fname'],
+ 'x_last_name' => $values['cc_lname'],
+ );
+
+ $fields = '';
+ foreach ($authNetValues as $i => $j) {
+ $fields .= "$i=" . urlencode($j) . '&';
+ }
+
+ $ch = curl_init($authNetUrl);
+ // set to 0 to elimindate header info from response
+ curl_setopt($ch, CURLOPT_HEADER, 0);
+ // Returns response data instead of TRUE(1)
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ // Use HTTP POST to send form data
+ curl_setopt($ch, CURLOPT_POSTFIELDS, rtrim($fields, "& "));
+ // Uncomment this line if you get no gateway response. ###
+ // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
+ // Execute post and get results
+ $resp = curl_exec($ch);
+ curl_close($ch);
+
+ $res = explode('|', $resp);
+ return $res;
+ }
+
+ // }}}
+ // {{{ 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)
+ {
+ $values['primary_contact'] = "{$values['fname']} {$values['lname']}";
+ unset($values['fname'], $values['lname']);
+
+ // 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 (preg_match('/^.+_rmv$/', $k)) {
+ unset($values[$k]);
+ }
+ }
+
+ Toolkit_Common::getTableMetaData();
+
+ return $this->insertData($values);
+ }
+
+ // }}}
+
+ // {{{ sendAdminEmail()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param boolean $test Parameter description (if any) ...
+ *
+ * @return boolean Return description (if any) ...
+ * @access public
+ */
+ public function sendAdminEmail($test = false)
+ {
+ if ($this->primaryAdvisee === false) {
+ return true;
+ } else {
+ $template = new HTML_Template_Flexy($this->flexyOptions);
+ $page = new stdClass();
+
+ $page->base_url = ($_SERVER['HTTPS'] == 'on') ? BASE_SECURE_URL :
+ BASE_URL;
+ $page->approval_needed = $this->approvalNeeded;
+ $page->member_name = $this->formData['member_name']['element'];
+ $page->client_name = SITENAME;
+ $page->email_from = OWNER_EMAIL;
+
+ $template->compile('addYourBusinessAdminEmail.tpl');
+ // Merge the compiled template with the $page object.
+ $htmlMsg = $template->bufferedOutputObject($page);
+
+ $msg = '';
+
+ $crlf = "\n";
+ $mimeMail = new Mail_mime($crlf);
+ $mimeMail->setFrom(SITENAME . " <{$page->email_from}>");
+ $mimeMail->setSubject('Add Your Business Request From ' . SITENAME);
+ if (!empty($this->secondaryAdvisees)) {
+ // Spam will choke if we CC: more than 5 addresses.
+ // so if the user puts more than 5 in, we'll only
+ // accept the first 5. This is stated in the property
+ // description for secondaryAdvisees
+ if (count($this->secondaryAdvisees) > 5) {
+ $this->secondaryAdvisees = array_slice($this->secondaryAdvisees, 0, 5);
+ }
+ foreach ($this->secondaryAdvisees as $k => $v) {
+ if (is_string($k) && !is_numeric($k)) {
+ $email = "$k <$v>";
+ } else {
+ $email = $v;
+ }
+ $mimeMail->addCC($email);
+ }
+ }
+ $mimeMail->setHTMLBody($htmlMsg);
+ $mimeMail->setTXTBody($msg);
+
+ // If we're testing the interface then don't actually send out the mail
+ $interface = $test ? 'mock' : 'mail';
+ $mail =& Mail::factory($interface);
+ $body = $mimeMail->get();
+ $headers = $mimeMail->headers($hdrs);
+
+ $res = $mail->send($this->primaryAdvisee, $headers, $body);
+
+ return PEAR::isError($res) ? Toolkit_Common::handleError($res) : $res;
+ }
+ }
+
+ // }}}
+ // {{{ sendMemberEmail()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param boolean $test Parameter description (if any) ...
+ *
+ * @return unknown Return description (if any) ...
+ * @access public
+ */
+ public function sendMemberEmail($test = false)
+ {
+ $template = new HTML_Template_Flexy($this->flexyOptions);
+ $page = new stdClass();
+
+ $page->base_url = ($_SERVER['HTTPS'] == 'on') ? BASE_SECURE_URL :
+ BASE_URL;
+ $page->member_category = MEMBERS_CATEGORY;
+ $page->approval_needed = $this->approvalNeeded;
+ $page->first_name = $this->formData['fname']['element'];
+ $page->member_name = $this->formData['member_name']['element'];
+ $page->username = $this->formData['member_login']['element'];
+ $page->password = $this->formData['member_passwd']['element'];
+ $page->client_name = SITENAME;
+
+ $template->compile('addYourBusinessMemberEmail.tpl');
+ // Merge the compiled template with the $page object.
+ $htmlMsg = $template->bufferedOutputObject($page);
+
+ $msg = '';
+
+ $crlf = "\n";
+ $mimeMail = new Mail_mime($crlf);
+ $mimeMail->setFrom(SITENAME . ' <'.OWNER_EMAIL.'>');
+ $mimeMail->setSubject('Add Your Business Request From ' . SITENAME);
+ $mimeMail->setHTMLBody($htmlMsg);
+ $mimeMail->setTXTBody($msg);
+
+ // If we're testing the interface then don't actually send out the mail
+ $interface = $test ? 'mock' : 'mail';
+ $mail =& Mail::factory($interface);
+ $body = $mimeMail->get();
+ $headers = $mimeMail->headers($hdrs);
+
+ $res = $mail->send($this->formData['member_contact_email']['element'], $headers, $body);
+
+ return PEAR::isError($res) ? Toolkit_Common::handleError($res) : $res;
+ }
+
+ // }}}
+ // {{{ setCategories()
+
+ /**
+ * Creates array structure of the category tree for use in a select element.
+ *
+ * This method will also instantiate a class property called tree for your
+ * class. This object will hold the tree structure of the categories list
+ * from the Database.
+ *
+ * @return array The array list of categories that can be loaded
+ * into a select element
+ *
+ * @access protected
+ */
+ protected function setCategories()
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM category
+ WHERE parent_id = 0
+ ORDER BY name";
+ foreach ($this->dbh->query($sql) as $row) {
+ $this->tree[] = new Toolkit_Members_CategoryTree($row['category_id'], $row['name'], $this->dbh);
+ }
+ if (!empty($this->tree)) {
+ foreach ($this->tree as $t) {
+ $this->createCategories($t);
+ }
+ }
+
+ if (empty($this->categories)) {
+ $this->categories = array('' => '-- No Categories Created Yet --');
+ } else {
+ $this->categories
+ = array('' => '-- Choose Category --') + $this->categories;
+ }
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ setConfig()
+
+ /**
+ * Sets the query to use to fetch the datagrid results
+ *
+ * @param Config_Container $c Configuration object
+ *
+ * @return void
+ * @access public
+ */
+ public function setConfig(Config_Container $c)
+ {
+ $this->config = $c;
+ }
+
+ // }}}
+ // {{{ setupRenderers()
+
+ /**
+ * Setup how the form should render
+ *
+ * We also need to attach a couple specific rendering templates to
+ * a few special elements.
+ *
+ * @return void
+ * @access protected
+ * @see Toolkit_FormBuilder::setupRenderers()
+ */
+ protected function setupRenderers()
+ {
+ parent::setupRenderers();
+ $renderer =& $this->defaultRenderer();
+ $required = '*';
+ $error = '
', 'captcha_rmv');
+ }
+
+ // }}}
+ // {{{ preventDuplicateMembers()
+
+ /**
+ * Sets the ability for duplicate member names to exist or not
+ *
+ * @param boolean $prevent true to reject, false to allow
+ *
+ * @return void
+ * @access public
+ */
+ public function preventDuplicateMembers($prevent = true)
+ {
+ $this->_preventDupNames = $prevent;
+ }
+
+ // }}}
+
+ // {{{ toHtml()
+
+ /**
+ * Call the rendering function to get the form in a string
+ *
+ * destroying and resetting the captcha value dis-allows someone from
+ * re-sending a form on a previous captcha.
+ *
+ * @return string The Form to be rendered or success msg.
+ * @access public
+ */
+ public function toHtml()
+ {
+ $this->setupRenderers();
+ if ($this->validate()) {
+ if ($this->includeCaptcha) {
+ $this->captchaQuestion->destroy();
+ }
+
+ $res = $this->process(array(&$this, 'processData'), $this->mergeFiles);
+
+ if ($res === true) {
+ $this->cleanForm();
+ $this->sendAdminEmail();
+ $this->sendMemberEmail();
+ $this->freeze();
+ $output = $this->successMsg;
+ if (is_array($this->authNetAccount)) {
+ $rem = array(
+ 'cc_cvv',
+ 'cc_type',
+ 'cc_fname',
+ 'cc_lname',
+ 'member_login',
+ 'member_passwd',
+ 'captcha_question',
+ );
+ foreach ($rem as $i) {
+ if ($this->elementExists($i)) {
+ $this->removeElement($i);
+ }
+ }
+
+ if ($this->elementExists('cc_num')) {
+ // Obscure th CC Num so its not displayed.
+ $e =& $this->getElement('cc_num');
+ $ccNum = $e->getValue();
+ $newCCNum = preg_replace(
+ '/\d/',
+ '*',
+ $ccNum,
+ strlen($ccNum) - 4
+ );
+ $e->setValue($newCCNum);
+ }
+ }
+ } elseif ($res == 2) {
+ $this->_errors['cc_num'] = 'ERROR: Your credit card has been declined!';
+ if ($this->includeCaptcha) {
+ $this->captchaQuestion->destroy();
+ $this->captchaAnswer->setValue('');
+ }
+ $output = $this->errorMsg;
+ $output .= parent::toHtml();
+ } else {
+ $this->_errors['cc_num'] = 'ERROR: There was an error processing your credit card!';
+ if ($this->includeCaptcha) {
+ $this->captchaQuestion->destroy();
+ $this->captchaAnswer->setValue('');
+ }
+ $output = $this->errorMsg;
+ $output .= parent::toHtml();
+ }
+ } else if ($this->isSubmitted()) {
+ if ($this->includeCaptcha) {
+ $this->captchaQuestion->destroy();
+ $this->captchaAnswer->setValue('');
+ }
+ $output = $this->errorMsg;
+ $output .= parent::toHtml();
+ } else {
+ if ($this->includeCaptcha) {
+ $this->captchaQuestion->destroy();
+ $this->captchaAnswer->setValue('');
+ }
+ $output = parent::toHtml();
+ }
+ return $output;
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/Admin/AddPhoto.php b/Toolkit/Members/Admin/AddPhoto.php
new file mode 100644
index 0000000..c416bdd
--- /dev/null
+++ b/Toolkit/Members/Admin/AddPhoto.php
@@ -0,0 +1,344 @@
+
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: AddPhoto.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit/Image/Server.php
+ */
+
+
+/**
+ * The image server processing class
+ */
+require_once BASE . 'Toolkit/Image/Server.php';
+
+/**
+ * Form to handle creating a new photo in the members only area
+ *
+ * Handles inserting new photo into db as a pending photo and creating a
+ * tuple in the member_updates table which will allow the admin to
+ * approve/deny the new photo request.
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Members_Admin_AddPhoto extends Toolkit_FormBuilder
+{
+ // {{{ properties
+
+ /**
+ * The table name in the database used to store the data
+ *
+ * @var string
+ * @access public
+ */
+ public $tableName = 'member_photos';
+
+ /**
+ * The template used to render the form
+ *
+ * @var string
+ * @access protected
+ */
+ protected $formTemplate = 'addPhoto.tpl';
+
+ /**
+ * Success message when a photo gets successfully uploaded
+ * @var string
+ * @access protected
+ */
+ protected $successMsg = '
+
+ You successfully uploaded your photo.
+
';
+
+ /**
+ * Description for protected
+ * @var array
+ * @access protected
+ */
+ protected $registeredRules = array();
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Class constructor
+ *
+ * @param PDO $pdo PHP Data Object to use for DB calls
+ * @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
+ * @see Toolkit_Members_Admin_EditPhotos
+ */
+ public function __construct(
+ $pdo,
+ $formName,
+ $method = 'post',
+ $action = '',
+ $target = '',
+ $attributes = null,
+ $trackSubmit = false
+ ) {
+ parent::__construct(
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+ $this->dbh = $pdo;
+ }
+
+ // }}}
+
+ // {{{ configureElements()
+
+ /**
+ * Setup the elements to use on the form.
+ *
+ * @param Config_Container $c application configuration
+ *
+ * @return void
+ * @access public
+ */
+ public function configureElements(Config_Container $c)
+ {
+ $e = array();
+
+ $config =& $c->getItem('section', 'photos');
+ $maxLength =& $config->getItem('directive', 'maxCaptionLength');
+ // All Grouped Elements are created here.
+
+ // All Elements are created here. This includes group element definitions.
+ $e[] = array(
+ 'type' => 'file',
+ 'req' => true,
+ 'name' => 'file',
+ 'display' => 'Upload a Photo',
+ 'opts' => array('class' => 'submit')
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'caption',
+ 'display' => 'Caption',
+ 'opts' => array(
+ 'class' => 'text',
+ 'maxlength' => $maxLength->getContent(),
+ ),
+ 'noCharLimit' => true
+ );
+ $e[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'submit',
+ 'display' => 'Upload new photo',
+ 'opts' => array('class' => 'submit')
+ );
+
+ $this->setupElements($e);
+ }
+
+ // }}}
+ // {{{ configureForm()
+
+ /**
+ * helper function to set up entire form definition
+ *
+ * @param Config_Container $c application configuration
+ *
+ * @return void
+ * @access public
+ */
+ public function configureForm(Config_Container $c)
+ {
+ $this->configureElements($c);
+ $this->configureRules($c);
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Configure rules for form
+ *
+ * @param Config_Container $c application configuration
+ *
+ * @return void
+ * @access public
+ */
+ public function configureRules(Config_Container $c)
+ {
+ $config =& $c->getItem('section', 'photos');
+ $maxLength =& $config->getItem('directive', 'maxCaptionLength');
+
+ $mimeTypes = array(
+ 'image/jpe',
+ 'image/jpeg',
+ 'image/jpg',
+ 'image/jfif',
+ 'image/pjpeg',
+ 'image/pjp',
+ 'image/gif',
+ 'image/png',
+ );
+
+ $r = array();
+
+ $r[] = array(
+ 'element' => 'file',
+ 'message' => 'ERROR: You must select a file!',
+ 'type' => 'uploadedfile',
+ 'format' => null,
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => 'caption',
+
+ 'message' => "ERROR: {$maxLength->getContent()} characters max!",
+ 'type' => 'maxlength',
+ 'format' => $maxLength->getContent(),
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => 'file',
+ 'message' => 'ERROR: Incorrect File Type (.gif, .png, .jpg) only!',
+ 'type' => 'mimetype',
+ 'format' => $mimeTypes,
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+
+ $this->setupRules($r);
+ }
+
+ // }}}
+
+ // {{{ processData()
+
+ /**
+ * Handles setting up the from processing and which function to get it done
+ *
+ * @param array $values Submitted values from the form.
+ *
+ * @return void
+ * @access protected
+ */
+ protected function processData($values)
+ {
+ try {
+ $sql = Toolkit_Common::createSQLInsert(
+ $this->tableName,
+ array_keys($values)
+ );
+
+ $res = Toolkit_Common::processQuery($this->dbh, $sql, $values);
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+
+ header('Location:' . $this->getAttribute('action'));
+ }
+
+ // }}}
+
+ // {{{ setupRenderers()
+
+ /**
+ * Set up the rendering engine we are going to use to display this form
+ *
+ * @param HTML_Template_Flexy &$tEngine Templating Engine
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers(HTML_Template_Flexy &$tEngine)
+ {
+ $renderer =& new HTML_QuickForm_Renderer_ObjectFlexy($tEngine);
+
+ $this->accept($renderer);
+ $this->view = new stdClass();
+ $this->view->form = $renderer->toObject();
+ $tEngine->compile($this->formTemplate);
+ }
+
+ // }}}
+
+ // {{{ toHtml()
+
+ /**
+ * Renders the form
+ *
+ * sets the page the form should be redirected to instead of coming back
+ * around to itself.
+ *
+ * @param HTML_Template_Flexy $tEngine Templating Engine
+ * @param Cache_Lite $cache Caching Engine
+ * @param Config_Container $c Application configuration
+ * @param Toolkit_Image_Server $is Image Server
+ * @param Toolkit_Members_Photos $ll Linked List of member photos
+ *
+ * @return string The rendered form
+ * @access public
+ */
+ public function toHtml(
+ HTML_Template_Flexy $tEngine,
+ Cache_Lite $cache,
+ Config_Container $c,
+ Toolkit_Image_Server $is,
+ Toolkit_Members_Photos $ll
+ ) {
+ if ($this->validate()) {
+ $cache->remove("Member-{$_GET['id']}", 'Profile');
+
+ // Put the processed photo's new name into the submitted values
+ $this->_submitValues['image'] = $is->imageUpload('file');
+ $this->_submitValues['pos'] = $ll->getListSize() + 1;
+ $this->_submitValues['member_id'] = $_GET['id'];
+ $this->_submitValues['pending'] = 0;
+
+ unset($this->_submitValues['MAX_FILE_SIZE'],
+ $this->_submitValues['submit']);
+
+ $this->process(array(&$this, 'processData'), false);
+ }
+
+ $this->setupRenderers($tEngine);
+
+ return $tEngine->bufferedOutputObject($this->view);
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/Admin/AuthorizeNewMemberForm.php b/Toolkit/Members/Admin/AuthorizeNewMemberForm.php
new file mode 100755
index 0000000..7a464db
--- /dev/null
+++ b/Toolkit/Members/Admin/AuthorizeNewMemberForm.php
@@ -0,0 +1,572 @@
+
+ * @copyright 2008 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: AuthorizeNewMemberForm.php,v 1.2 2009/12/15 20:18:15 jamie Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+require_once 'FormBuilder.php';
+
+/**
+ * Description for require_once
+ */
+require_once 'HTML/Template/Flexy.php';
+
+/**
+ * Description for require_once
+ */
+require_once 'Mail/mime.php';
+
+/**
+ * Description for require_once
+ */
+require_once 'Mail.php';
+
+/**
+ * Creates, Renders, Processes form for request to be added to Business DB
+ *
+ * This Form just sends the primary advisee an HTML email of the data
+ * that was filled in and requires them to add the users to the Business DB
+ * themselves.
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2008 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Members_Admin_AuthorizeNewMemberForm extends Toolkit_FormBuilder
+{
+ // {{{ properties
+
+ /**
+ * PDO connections
+ *
+ * @var string
+ * @access public
+ */
+ public $dbh;
+
+ /**
+ * The name of the DB table that holds the member records
+ *
+ * @var array
+ * @access protected
+ */
+ public $tableName = 'member';
+
+ /**
+ * States array for select list
+ *
+ * @var array
+ * @access protected
+ */
+ protected $states;
+
+ /**
+ * What do you want the success msg to be if the form validates successfully
+ *
+ * @var string
+ * @access protected
+ */
+ protected $successMsg = '';
+
+ /**
+ * Primary email address to send notification a record has been updated
+ *
+ * Set this value to false and it will turn off the email
+ * update notifications.
+ *
+ * @var string
+ * @access protected
+ */
+ protected $primaryAdvisee = 'jamie@gaslightmedia.com';
+
+ /**
+ * Flexy options used in the renderer
+ *
+ * @var array
+ * @access protected
+ */
+ protected $flexyOptions;
+
+ /**
+ * The name of the template used to email the owner for any updates
+ *
+ * When a member makes an update to thier record, this is the template
+ * we will use to send out the email notification to the site owner.
+ *
+ * @var string
+ * @access protected
+ */
+ protected $emailTemplate = 'addYourBusinessEmailOwner.tpl';
+
+ /**
+ * The flexy template object which holds the rendered object
+ *
+ * @var object
+ * @access protected
+ */
+ protected $template;
+
+ // }}}
+
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * @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
+ * @see Toolkit_FormBuilder, HTML_QuickForm
+ */
+ public function __construct(
+ $formName,
+ $method = 'post',
+ $action = '',
+ $target = '',
+ $attributes = null,
+ $trackSubmit = false
+ ) {
+ parent::__construct(
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+ $this->template = dirname(__FILE__) . '/../templates/currentTables/';
+ $this->states = $states_US;
+ $this->registeredRules = array('zip', 'phone', 'memberlogo');
+
+ $this->dbh = Toolkit_Database::getInstance();
+
+ /**
+ * Where are the flexy templates stored at for this class.
+ */
+ define('TEMPLATES_DIR', BASE . 'Toolkit/Members/templates');
+
+ /**
+ * Where are the compiled flexy templates stored at for this class.
+ */
+ define('COMPILED_DIR', BASE . 'Toolkit/Members/templates/compiled');
+
+ $oldUmask = umask(0);
+ if (!is_dir(TEMPLATES_DIR)) {
+ mkdir(TEMPLATES_DIR, 0770, true);
+ }
+ if (!is_dir(COMPILED_DIR)) {
+ mkdir(COMPILED_DIR, 0770, true);
+ }
+ umask($oldUmask);
+
+ $this->flexyOptions = $GLOBALS['flexyOptions'];
+ $this->flexyOptions['templateDir'] = TEMPLATES_DIR;
+ $this->flexyOptions['compileDir'] = COMPILED_DIR;
+
+ $this->configureElements();
+ $this->configureRules();
+ $this->configureFilters();
+ $this->configureDefaults();
+ $this->configureConstants();
+ }
+
+ // }}}
+
+ // {{{ approveMember()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @return mixed Return description (if any) ...
+ * @access protected
+ */
+ protected function approveMember()
+ {
+ try {
+ $sql = "
+ UPDATE {$this->tableName}
+ SET new_member = false
+ WHERE member_id = ?";
+
+ $stmt = $this->dbh->prepare($sql);
+ return $stmt->execute(array($_GET['id']));
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ denyMember()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @return mixed Return description (if any) ...
+ * @access protected
+ */
+ protected function denyMember()
+ {
+ try {
+ $sql = "
+ DELETE FROM {$this->tableName}
+ WHERE member_id = ?";
+
+ $stmt = $this->dbh->prepare($sql);
+ return $stmt->execute(array($_GET['id']));
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ configureConstants()
+
+ /**
+ * Sets the constants for the form
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureConstants()
+ {
+ $c = array(
+ 'new_member' => 0,
+ );
+
+ $this->setupConstants($c);
+ }
+
+ // }}}
+ // {{{ configureDefaults()
+
+ /**
+ * Sets the defaults for the form
+ *
+ * @return array $defaults Returns the array of defaults
+ * so children who call this function
+ * can obtain a copy of these values.
+ * @access protected
+ * @see Toolkit_FormBuilder::setupDefaults()
+ */
+ protected function configureDefaults()
+ {
+ $defaults = array();
+
+ try {
+ if (is_numeric($_GET['id'])) {
+ $sql = "
+ SELECT m.*, c.name AS category
+ FROM {$this->tableName} m
+ JOIN member_category mc USING (member_id)
+ JOIN category c USING (category_id)
+ WHERE m.member_id = :mid
+ AND m.new_member = true";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':mid', $_GET['id'], PDO::PARAM_INT);
+ $stmt->execute();
+ if ($row = $stmt->fetch()) {
+ foreach ($row as $i => $j) {
+ $defaults[$i] = $j;
+ }
+ }
+
+ }
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+
+ $this->setupDefaults($defaults);
+ return $defaults;
+ }
+
+ // }}}
+ // {{{ configureElements()
+
+ /**
+ * Setup the elements to use on the form.
+ *
+ * @return void
+ * @access protected
+ * @see Toolkit_FormBuilder::setupElements()
+ */
+ protected function configureElements()
+ {
+ $e = array();
+ // All Grouped Elements are created here.
+
+ // All Elements are created here. This includes group element definitions.
+ $submitBtns[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'approve',
+ 'display' => 'Approve',
+ 'opts' => array('id' => 'approve')
+ );
+ $submitBtns[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'deny',
+ 'display' => 'Deny',
+ 'opts' => array('id' => 'deny')
+ );
+
+ // Member Information
+ $e[] = array(
+ 'type' => 'hidden',
+ 'req' => false,
+ 'name' => 'new_member'
+ );
+ $e[] = array(
+ 'type' => 'header',
+ 'req' => false,
+ 'name' => 'newMemberHdr',
+ 'display' => 'New ' . Toolkit_Members_Admin_Controller::$listingType['singular'] . ' Request Information'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'member_name',
+ 'display' => Toolkit_Members_Admin_Controller::$listingType['singular'] . ' Name'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'primary_contact',
+ 'display' => 'Primary Contact'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'member_contact_email',
+ 'display' => 'Email'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'phone',
+ 'display' => 'Phone'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'category',
+ 'display' => 'Category'
+ );
+ $e[] = array(
+ 'type' => 'group',
+ 'req' => false,
+ 'name' => 'decision',
+ 'group' => $submitBtns,
+ 'seperator' => '',
+ 'appendName' => false
+ );
+
+ $this->setupElements($e);
+ }
+
+ // }}}
+ // {{{ configureFilters()
+
+ /**
+ * Setup the filters to apply to the elements before we are
+ * handed the values submitted
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureFilters()
+ {
+ $f = array();
+ $f[] = array(
+ 'element' => '__ALL__',
+ 'filter' => 'trim'
+ );
+
+ $this->setupFilters($f);
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Sets up all the rules to be used when the form is validated.
+ *
+ * @return void
+ * @access Protected
+ */
+ protected function configureRules()
+ {
+ $this->setupRules($rules);
+ }
+
+ // }}}
+ // {{{ emailMember()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param unknown $status Parameter description (if any) ...
+ * @param boolean $test Parameter description (if any) ...
+ *
+ * @return unknown Return description (if any) ...
+ * @access public
+ */
+ public function emailMember($status, $test = false)
+ {
+ $template = new HTML_Template_Flexy($this->flexyOptions);
+ $page = new stdClass();
+
+ $data = $this->configureDefaults();
+ $page->base_url = ($_SERVER['HTTPS'] == 'on') ? BASE_SECURE_URL :
+ BASE_URL;
+ $page->client_name = SITENAME;
+ $page->member_login = $data['member_login'];
+ $page->member_passwd = $data['member_passwd'];
+ $page->first_name = strtok($data['primary_contact'], ' ');
+ $page->member_category = MEMBERS_CATEGORY;
+
+ $tpl = $status ? 'newMemberApproval.tpl' : 'newMemberDenial.tpl';
+ $template->compile($tpl);
+ // Merge the compiled template with the $page object.
+ $htmlMsg = $template->bufferedOutputObject($page);
+
+ $crlf = "\n";
+ $mimeMail = new Mail_mime($crlf);
+ $mimeMail->setFrom(SITENAME . ' <' . OWNER_EMAIL . '>');
+ $mimeMail->setSubject('New ' . Toolkit_Members_Admin_Controller::$listingType['singular'] . ' Request');
+ $mimeMail->setHTMLBody($htmlMsg);
+ $mimeMail->setTXTBody($msg);
+
+ $interface = $test ? 'mock' : 'mail';
+ $mail =& Mail::factory($interface);
+ $body = $mimeMail->get();
+ $headers = $mimeMail->headers($hdrs);
+
+ try {
+ $sql = "
+ SELECT member_contact_email
+ FROM {$this->tableName}
+ WHERE member_id = ?";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->execute(array($_GET['id']));
+ $stmt->bindColumn('member_contact_email', $email);
+ $stmt->fetch();
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+
+ $res = $mail->send($email, $headers, $body);
+
+ return PEAR::isError($res) ? Toolkit_Common::handleError($res) : $res;
+ }
+
+ // }}}
+
+ // {{{ 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)
+ {
+ if (array_key_exists('deny', $values)) {
+ $this->emailMember(false);
+ return $this->denyMember();
+ } elseif (array_key_exists('approve', $values)) {
+ $this->emailMember(true);
+ return $this->approveMember();
+ }
+ }
+
+ // }}}
+
+ // {{{ setupRenderers()
+
+ /**
+ * Setup how the form should render
+ *
+ * We also need to attach a couple specific rendering templates to
+ * a few special elements.
+ *
+ * @return void
+ * @access protected
+ * @see Toolkit_FormBuilder::setupRenderers()
+ */
+ protected function setupRenderers()
+ {
+ parent::setupRenderers();
+ $renderer =& $this->defaultRenderer();
+ $required = '*';
+ $error = '
{error}
';
+
+ $renderer->setElementTemplate('
{element}
', 'decision');
+ }
+
+ // }}}
+
+ // {{{ toHTML()
+
+ /**
+ * Call the rendering function to get the form in a string
+ *
+ * @access protected
+ * @return string $output The Form to be rendered or success msg.
+ */
+ public function toHTML()
+ {
+ $this->setupRenderers();
+ $this->freeze();
+ if ($this->validate()) {
+ $this->cleanForm();
+ if ($this->process(array(&$this, 'processData'), $this->mergeFiles)) {
+ header('Location: ' . BASE_URL . 'admin/members.php?cat=2&subCat=4');
+ }
+ } else if ($this->isSubmitted()) {
+ $output = $this->errorMsg;
+ $output .= parent::toHTML();
+ } else {
+ $output = parent::toHTML();
+ }
+ return $output;
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/Admin/AuthorizeUpdates.php b/Toolkit/Members/Admin/AuthorizeUpdates.php
new file mode 100755
index 0000000..9fd3e0f
--- /dev/null
+++ b/Toolkit/Members/Admin/AuthorizeUpdates.php
@@ -0,0 +1,1681 @@
+
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: AuthorizeUpdates.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Handle processing all the update requests from members
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2008 Gaslight media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Members_Admin_AuthorizeUpdates extends Toolkit_FormBuilder
+{
+ // {{{ properties
+
+ /**
+ * The member we are going to process updates for
+ *
+ * @var integer
+ * @access private
+ */
+ private $_mid;
+
+ /**
+ * The Table name used to store the data of the member record in the database.
+ *
+ * @var string
+ * @access public
+ */
+ public $tableName = 'member_updates';
+
+ /**
+ * Array of data that holds the meta data info on the table
+ *
+ * Contains information on the type of fields in the database.
+ * That way when we run our automated SQL queries with our PDO
+ * we can properly bind data to our SQL queries. This will
+ * allow for one more layer of protection against any sql
+ * injection attempts.
+ *
+ * @var string
+ * @access public
+ * @see Toolkit_Common::processData()
+ */
+ public $tableMetaData;
+
+ /**
+ * The name of the template used to render the business info form.
+ *
+ * @var string
+ * @access protected
+ */
+ protected $formTemplate = 'authorizeChanges.tpl';
+
+ /**
+ * Form access from inside the template
+ *
+ * @var object
+ * @access protected
+ */
+ protected $view;
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * @param PDO $pdo PHP Data Object to use for DB calls
+ * @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
+ ) {
+ parent::__construct(
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+
+ $this->dbh = $pdo;
+
+ $this->flexyOptions = Toolkit_Members::getFlexyOptions();
+ }
+
+ // }}}
+
+ // {{{ commitUpdates
+
+ /**
+ * Commit the updates requested by the member
+ *
+ * @param string $table The table to commit any updates for
+ * @param array $fields The fields to update
+ * @param array $updates The updates
+ *
+ * @return boolean true on success, false on error
+ * @access protected
+ */
+ protected function commitUpdates($table, array $fields, array $updates)
+ {
+ foreach ($fields as $k => &$v) {
+ $orig = $v;
+ list ($id, $v) = explode('_', $v, 2);
+ if (array_key_exists("{$orig}_update", $updates)) {
+ $updates["{$v}_update"] = $updates["{$orig}_update"];
+ unset($updates["{$orig}_update"]);
+ }
+ }
+ try {
+ $this->dbh->beginTransaction();
+ // This will be the query we will use at the end to update the
+ // members record.
+ $sql = $this->getUpdateQuery($table, $fields);
+
+ // hack to fix states trying to update w/ the
+ // text ie (North Carolina - go heels!) vs. field id.
+ unset($updates['state_id_update']);
+ $updateStmt = $this->dbh->prepare($sql);
+ $updateStmt->bindParam(':member_id', $this->_mid, PDO::PARAM_INT);
+
+ // This will be the query we will use to remove the updates
+ // from the update table. By removing the field from the updates
+ // table it takes that field out of a "pending" state, by removing all
+ // of the fields for a member out of the updates table it removes
+ // that member from being in a "pending" state.
+ $sql = "
+ DELETE FROM {$this->tableName}
+ WHERE field = :field
+ AND member_id = :member_id";
+
+ $deleteStmt = $this->dbh->prepare($sql);
+ $deleteStmt->bindParam(':member_id', $this->_mid, PDO::PARAM_INT);
+
+ // This will be the query we will use to get the updated fields
+ // information.
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE id in (
+ SELECT max(id)
+ FROM {$this->tableName}
+ WHERE member_id = :member_id
+ AND field = :field)";
+
+ $fetchStmt = $this->dbh->prepare($sql);
+ $fetchStmt->bindParam(':member_id', $this->_mid, PDO::PARAM_INT);
+ foreach ($fields as $k => &$f) {
+ unset($v);
+ // Get the newest row for this field for this member.
+ $fetchStmt->bindParam(':field', $f, PDO::PARAM_STR);
+ $fetchStmt->execute();
+ $row = $fetchStmt->fetch(PDO::FETCH_ASSOC);
+
+ // Get the update to apply.
+ if (array_key_exists("{$f}_update", $updates)) {
+ $v = $updates["{$f}_update"];
+ } else {
+ $v = $row['update'];
+ }
+
+ // Get the dataType for the PDO Statement.
+ $metaData = $row['data_type'];
+ if ($metaData == 'integer') {
+ $dataType = PDO::PARAM_INT;
+ } else if ($metaData == 'boolean') {
+ $dataType = PDO::PARAM_BOOL;
+ } else {
+ $dataType = PDO::PARAM_STR;
+ }
+ // for empty values that are not actually a zero (0), we
+ // want to insert null's.
+ // This will help hold the unique values for member_logins,
+ // as empty values '', are not considered unique
+ if (empty($v) && $v !== 0) {
+ $v = null;
+ $dataType = PDO::PARAM_NULL;
+ }
+ // Bind the update for later execution.
+ $updateStmt->bindParam(":$f", $v, $dataType);
+
+ // Remove this field from the updates
+ $deleteStmt->bindParam(':field', $f, PDO::PARAM_STR);
+ $deleteStmt->execute();
+ }
+ $updateStmt->execute();
+ return $this->dbh->commit();
+ } catch (PDOException $e) {
+ $this->dbh->rollback();
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ configureDefaults()
+
+ /**
+ * Sets the defaults for the an existing member
+ *
+ * Populates data for the main member form. Also grabs
+ * data to populate the modules on the form if needed.
+ *
+ * @return array $defaults Returns the array of defaults
+ * so children who call this function
+ * can obtain a copy of these values.
+ * @access public
+ */
+ public function configureDefaults()
+ {
+ $updatedFieldValues = $this->getUpdatedFieldValues();
+ $originalFieldValues = $this->getOriginalFieldValues();
+
+ if (is_array($updatedFieldValues)) {
+ $defaults = $updatedFieldValues;
+ }
+
+ if (is_array($originalFieldValues)) {
+ if (is_array($defaults)) {
+ $defaults += $originalFieldValues;
+ } else {
+ $defaults = $originalFieldValues;
+ }
+ }
+
+ $this->setupDefaults($defaults);
+ return $defaults;
+ }
+
+ // }}}
+ // {{{ configureElements()
+
+ /**
+ * Setup the elements to use on the form.
+ *
+ * Categories are populated into the protected class property $categories.
+ * These categories are used to populate the select list of categories.
+ * Modules are configured before any elements are setup, that way we will
+ * know if we need to include them in the rendering of the form.
+ *
+ * @return void
+ * @access public
+ */
+ public function configureElements()
+ {
+ // Get the newest updates in the update table for this member
+ // for each field that was updated.
+ try {
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE id IN (
+ SELECT max(id)
+ FROM {$this->tableName}
+ WHERE member_id = :member_id
+ GROUP BY field, foreign_key)
+ ORDER BY db_table, foreign_key, id";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $this->_mid, PDO::PARAM_INT);
+ $stmt->execute();
+ while ($row = $stmt->fetch()) {
+ // If we are dealing w/ a credit card, this
+ // will extract the name of the card.
+ // Otherwise, it will leave the value unchanged.
+ $pattern = '/creditCards\[(.+)\]/';
+ $replacement = '$1';
+ $row['field'] = preg_replace($pattern, $replacement, $row['field']);
+ $updates[] = $row;
+ switch ($row['field_type']) {
+ case 'select' :
+ case 'checkbox' :
+ $elementsToFreeze[$row['id']] = $row['field'];
+ break;
+
+ default :
+ break;
+ }
+ }
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+
+ if (is_array($updates)) {
+ // We're going to need to alter how some of the fields
+ // are displayed on the page. This is where we set them up.
+ foreach ($updates as $u) {
+ unset($type, $opts);
+ // Determine which fields should be a text field so
+ // the admin can update them w/ thier own text.
+ switch ($u['data_type']) {
+ case 'text' :
+ case 'integer' :
+ $textField = true;
+ break;
+
+ default :
+ $textField = false;
+ break;
+ }
+ if ($textField) {
+ switch ($u['label']) {
+ case 'Description' :
+ case 'Special Package Description' :
+ case 'Golf Package Description' :
+ $type = 'textarea';
+ $opts = array(
+ 'id' => 'd' . microtime(),
+ 'rows' => 8,
+ 'cols' => 43,
+ );
+ break;
+
+ default :
+ $type = 'text';
+ $opts = array('class' => 'text');
+ break;
+ }
+ }
+ // If we are dealing w/ the fields for the restaurant module
+ // we need to alter the labels of the text fields.
+ // Otherwise we could potentially have multiple [To] or [From]
+ // fields and no way to discern which meal they represent.
+ if ($u['db_table'] == 'member_restaurants') {
+ if ($u['data_type'] == 'text') {
+ $u['label'] = ucwords(str_replace('_', ' ', $u['field']));
+ }
+ }
+ if ($u['db_table'] == 'member' && $u['field'] == 'logo') {
+ $u['label'] = '
+ Logo
';
+ }
+ if ($u['db_table'] == 'member_packages' && $u['field'] == 'image') {
+ unset($type, $opts);
+ }
+ if (!isset($type)) {
+ $type = 'static';
+ }
+ $labels[$u['id']][$u['field']]['label'] = $u['label'];
+ $labels[$u['id']][$u['field']]['db_table'] = $u['db_table'];
+
+ $fields[$u['id']][$u['field']][] = array('type' => 'static', 'req' => false, 'name' => "{$u['id']}_{$u['field']}_orig");
+ $fields[$u['id']][$u['field']][] = array('type' => $type, 'req' => false, 'name' => "{$u['id']}_{$u['field']}_update", 'opts' => $opts);
+ }
+
+ $elements[] = array('type' => 'header', 'req' => false, 'name' => 'memberInfoHdr', 'display' => 'Updates', 'col1' => true);
+ foreach ($fields as $rowid => $field) {
+ foreach ($field as $k => $arr) {
+ if ($table != $labels[$rowid][$k]['db_table']) {
+ $elements[] = array('type' => 'header', 'req' => false, 'name' => 'table', 'display' => ucwords(str_replace('_', ' ', $labels[$rowid][$k]['db_table'])));
+ $table = $labels[$rowid][$k]['db_table'];
+ }
+ $elements[] = array('type' => 'group', 'req' => false, 'name' => "{$rowid}_{$k}", 'group' => $field[$k], 'label' => $labels[$rowid][$k]['label'], 'seperator' => ' ', 'appendName' => false);
+ }
+ }
+ }
+
+ $this->setupElements($elements);
+
+
+ if (!empty($elementsToFreeze)) {
+ foreach ($elementsToFreeze as $k => $v) {
+ $eName = "{$k}_{$v}";
+ if ($this->elementExists($eName)) {
+ $e =& $this->getElement($eName);
+ if (PEAR::isError($e)) {
+ return Toolkit_Common::handleError($e);
+ } else {
+ $e->freeze();
+ }
+ }
+ }
+ }
+ }
+
+ // }}}
+ // {{{ configureFilters()
+
+ /**
+ * Setup the filters to apply to the elements before we are
+ * handed the values submitted
+ *
+ * @return void
+ * @access public
+ */
+ public function configureFilters()
+ {
+ $filters[] = array('element' => '__ALL__', 'filter' => 'trim');
+
+ $this->setupFilters($filters);
+ }
+
+ // }}}
+ // {{{ configureForm()
+
+ /**
+ * Wrapper function to handle setting up the form
+ *
+ * @return mixed PEAR error if no member id is set, otherwise true
+ * @access public
+ */
+ public function configureForm()
+ {
+ if (!is_numeric($this->_mid)) {
+ return PEAR::raiseError('Invalid member id');
+ }
+
+ $this->configureElements();
+ $this->configureFilters();
+ //$this->configureRules();
+ $this->configureDefaults();
+
+ return true;
+ }
+
+ // }}}
+ // {{{ configureModules()
+
+ /**
+ * Turns on a modules if the member has the appropriate category
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureModules()
+ {
+ if (is_array($this->memberCategories)) {
+ try {
+ $sql = "
+ SELECT *
+ FROM category
+ WHERE category_id = :cid";
+
+ $stmt = $this->dbh->prepare($sql);
+ foreach ($this->memberCategories as $cid => $v) {
+ $stmt->bindParam(':cid', $cid, PDO::PARAM_INT);
+ $stmt->execute();
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+ if ($row['accommodations'] == 't') {
+ $this->accommodations = true;
+ }
+ if ($row['restaurant'] == 't') {
+ $this->restaurant = true;
+ }
+ if ($row['golf'] == 't') {
+ $this->golf = true;
+ }
+ }
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Sets up all the rules to be used when the form is validated.
+ *
+ * @return void
+ * @access public
+ */
+ public function configureRules()
+ {
+ // Define the rules for each element in the group.
+ $num_rule = array('ERROR: Must contain a valid positive or negative decimal number!', 'numeric');
+ // Collect together the rules for each element.
+ $lat_rules = array('lat' => array($num_rule));
+ $lon_rules = array('lon' => array($num_rule));
+
+ $rules[] = array('element' => 'reservation_id', 'message' => 'ERROR: Must be an integer!', 'type' => 'numeric', 'format' => null, 'validation' => $this->validationType, 'reset' => false, 'force' => false);
+ $rules[] = array('element' => 'num_rooms', 'message' => 'ERROR: Must be an integer!', 'type' => 'numeric', 'format' => null, 'validation' => $this->validationType, 'reset' => false, 'force' => false);
+ $rules[] = array('element' => 'latitude', 'message' => 'ERROR:', 'type' => 'group', 'format' => $lat_rules, 'validation' => $this->validationType, 'reset' => false, 'force' => false);
+ $rules[] = array('element' => 'longitude', 'message' => 'ERROR:', 'type' => 'group', 'format' => $lon_rules, 'validation' => $this->validationType, 'reset' => false, 'force' => false);
+ $rules[] = array('element' => 'member_name', 'message' => 'ERROR: Name Already used!', 'type' => 'callback', 'format' => array($this, 'checkMemberName'), 'validation' => $this->validationType, 'reset' => false, 'force' => false);
+ $rules[] = array('element' => 'member_login', 'message' => 'ERROR: Already used, Please choose another!', 'type' => 'callback', 'format' => array($this, 'checkUName'), 'validation' => $this->validationType, 'reset' => false, 'force' => false);
+ $rules[] = array('element' => 'zip', 'message' => 'ERROR: Invalid Zip Code!', 'type' => 'zip', 'format' => array('requireDBCheck' => false), 'validation' => $this->validationType, 'reset' => false, 'force' => false);
+ $rules[] = array('element' => 'phone', 'message' => 'ERROR: Invalid Phone Number!','type' => 'phone', 'format' => null, 'validation' => $this->validationType, 'reset' => false, 'force' => false);
+ $rules[] = array('element' => 'fax', 'message' => 'ERROR: Invalid Phone Number!','type' => 'phone', 'format' => null, 'validation' => $this->validationType, 'reset' => false, 'force' => false);
+
+ $this->setupRules($rules);
+ }
+
+ // }}}
+
+ // {{{ getMultipleFieldUpdates()
+
+ /**
+ * Gets the current values for multiple fields of members
+ *
+ * Multiple fields are ones that a member can have many of. They idealy
+ * need a foreign key, but it is impossible to set up dynamic foreign keys.
+ * examples of these fields are photo captions or file name, or newly added
+ * files. Since a member can have multiple of these fields pending at the
+ * same time, we need to figure out the original value for the file names,
+ * captions, etc... of these fields.
+ *
+ * To get these fields, figure out which ones have updates in the updates
+ * table and get corresponding field from the original table. Then use the
+ * psuedo foreign_key to get the corresponding match in the actual table.
+ *
+ * @return array All the original updates made by the member
+ * @access protected
+ * @see Toolkit_Members_authorizeupdates::getOriginalFieldValues()
+ */
+ protected function getMultipleFieldUpdates()
+ {
+ $tables = array();
+ // Then we need to get all the tables which DO NOT have DISTINCT
+ // fields in the updates table. That means they DO have a
+ // psuedo foreign_key pointing back to them. These are going
+ // to take a little more work to obtain the original values.
+ $sql = "
+ SELECT DISTINCT db_table
+ FROM {$this->tableName}
+ WHERE foreign_key is NOT NULL";
+ foreach ($this->dbh->query($sql) as $row) {
+ $tables[] = $row['db_table'];
+ }
+
+ if (empty($tables)) {
+ return $tables;
+ }
+
+ // This query will get all the fields that we need to get
+ // from the original table.
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE id in (
+ SELECT max(id)
+ FROM {$this->tableName}
+ WHERE db_table = :db_table
+ AND member_id = :member_id
+ GROUP BY field, foreign_key)";
+
+ $getFieldStmt = $this->dbh->prepare($sql);
+ $getFieldStmt->bindParam(':member_id', $this->_mid, PDO::PARAM_INT);
+
+ $defaults = array();
+ foreach ($tables as $t) {
+ $getFieldStmt->bindParam(':db_table', $t, PDO::PARAM_STR);
+ $getFieldStmt->execute();
+
+ // This query will get the current value that the member
+ // has stored in the DB for the field we want.
+ $sql = "
+ SELECT %s
+ FROM $t
+ WHERE id = %d";
+
+ while ($row = $getFieldStmt->fetch()) {
+ if ($row['data_type'] == 'text') {
+ $newSql = sprintf($sql, $row['field'], $row['foreign_key']);
+ $current
+ = $this->dbh->query($newSql)->fetch();
+ if (empty($current[$row['field']])) {
+ $current[$row['field']] = 'Did not previously exist.';
+ } elseif ($t == 'member_packages') {
+ if ($row['field'] == 'image') {
+ $current[$row['field']]
+ = '
Old
+
+
';
+ }
+ }
+ $defaults["{$row['id']}_{$row['field']}_orig"]
+ = $current[$row['field']];
+ }
+ }
+ }
+
+ return $defaults;
+ }
+
+ // }}}
+ // {{{ getOriginalFieldValues()
+
+ /**
+ * Gets all the original values for the fields that have pending updates
+ *
+ * @return array of updates for all the fields that the member sent
+ * @access protected
+ */
+ protected function getOriginalFieldValues()
+ {
+ try {
+ $staticUpdates = $this->getSingleFieldUpdates();
+ $dynamicUpdates = $this->getMultipleFieldUpdates();
+
+ $defaults = array_merge($staticUpdates, $dynamicUpdates);
+
+ return $defaults;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ getSingleFieldUpdates()
+
+ /**
+ * Gets the current values for single fields of members
+ *
+ * Single fields are ones that can only show reference one field from
+ * the updates table to a member. Such as, url, description, num_rooms,
+ * etc...
+ * These field will only come from the member table or any member module
+ * table (golf, restaurant, accommodations).
+ *
+ * To get these fields, figure out which ones have updates in the updates
+ * table and get corresponding field from the original table.
+ *
+ * @return array
+ * @access protected
+ * @see Toolkit_Members_authorizeupdates::getOriginalFieldValues()
+ */
+ protected function getSingleFieldUpdates()
+ {
+ $tables = array();
+ // We need to get all the tables which have DISTINCT fields
+ // in the updates table. That means they do not have a
+ // psuedo foreign_key pointing back to them. These will be
+ // easier to get the original values for.
+ $sql = "
+ SELECT DISTINCT db_table
+ FROM {$this->tableName}
+ WHERE foreign_key is null";
+ foreach ($this->dbh->query($sql) as $row) {
+ $tables[] = $row['db_table'];
+ }
+
+ if (empty($tables)) {
+ return $tables;
+ }
+
+ // This query will get all the fields that we need to get
+ // from the original table.
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE id in (
+ SELECT max(id)
+ FROM {$this->tableName}
+ WHERE db_table = :db_table
+ AND member_id = :member_id
+ GROUP BY field)";
+
+ $getFieldStmt = $this->dbh->prepare($sql);
+ $getFieldStmt->bindParam(':member_id', $this->_mid, PDO::PARAM_INT);
+
+ $defaults = array();
+ // We need to get all the tables which have DISTINCT fields
+ foreach ($tables as &$t) {
+ $getFieldStmt->bindParam(':db_table', $t, PDO::PARAM_STR);
+ $getFieldStmt->execute();
+
+ // This query will get the current value that the member
+ // has stored in the DB for the field we want.
+ $sql = "
+ SELECT %s
+ FROM $t
+ WHERE member_id = {$this->_mid}";
+
+ while ($row = $getFieldStmt->fetch()) {
+ if ($row['data_type'] == 'text') {
+ $newSql = sprintf($sql, $row['field']);
+ $current
+ = $this->dbh->query($newSql)->fetch();
+
+ $defaults["{$row['id']}_{$row['field']}_orig"]
+ = $current[$row['field']];
+ }
+ if ($row['field'] == 'state_id') {
+ $locationNames = '
+ ,(
+ select state_name
+ from state
+ where state.state_id = member.state_id) as state_id';
+
+ $newSql = sprintf($sql, $row['field'] . $locationNames);
+ $current
+ = $this->dbh->query($newSql)->fetch();
+
+ $defaults["{$row['id']}_{$row['field']}_orig"]
+ = $current[$row['field']];
+ }
+ }
+ }
+
+ return $defaults;
+ }
+
+ // }}}
+ // {{{ getUpdateQuery()
+
+ /**
+ * Get the update query for a table in the database
+ *
+ * @param string $tname The table name to update in the database
+ * @param array $accepted All the accepted updates/changes
+ *
+ * @return string The update query to run against the database
+ * @access protected
+ */
+ protected function getUpdateQuery($tname, array $accepted)
+ {
+ $params = array_values($accepted);
+ $length = count($params);
+ for ($i = 0; $i < $length; ++$i) {
+ $bindParams .= "{$params[$i]} = :{$params[$i]}";
+ if ($i < ($length - 1)) {
+ $bindParams .= ', ';
+ }
+ }
+ $sql = "
+ UPDATE $tname
+ SET $bindParams
+ WHERE member_id = :member_id";
+ return $sql;
+ }
+
+ // }}}
+ // {{{ getUpdatedFieldValues()
+
+ /**
+ * Gets all the values for the newest updates
+ *
+ * @return array The updated values
+ * @access protected
+ */
+ protected function getUpdatedFieldValues()
+ {
+ try {
+ // Get all the latest updates, When we are dealing w/ the state_id
+ // fields, get the state name vs showing the id number.
+ // users won't know what the # is.
+ $sql = "
+ SELECT *,
+ CASE
+ WHEN field = 'state_id' THEN (
+ SELECT state_name
+ FROM state
+ WHERE state_id = CAST(UPDATE AS integer) )
+ WHEN field ~* 'creditCards' AND update = '0' THEN 'Removed'
+ WHEN field ~* 'creditCards' AND update = '1' THEN 'Added'
+ WHEN db_table = 'member_amenity' AND update = '0' THEN 'Removed'
+ WHEN db_table = 'member_amenity' AND update = '1' THEN 'Added'
+ ELSE UPDATE END AS
+ UPDATE
+ FROM {$this->tableName}
+ WHERE id IN (
+ SELECT MAX(id)
+ FROM {$this->tableName}
+ WHERE member_id = :member_id
+ GROUP BY field, foreign_key)
+ ORDER BY db_table, foreign_key, id";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $this->_mid, PDO::PARAM_INT);
+ $stmt->execute();
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ // If we are dealing w/ a credit card, this
+ // will extract the name of the card.
+ // Otherwise, it will leave the value unchanged.
+ $pattern = '/creditCards\[(.+)\]/';
+ $replacement = '$1';
+ $row['field'] = preg_replace($pattern, $replacement, $row['field']);
+ if (empty($row['update'])) {
+ if ($row['data_type'] == 'boolean') {
+ $row['update'] = 'Off';
+ }
+ } elseif ($row['data_type'] == 'boolean') {
+ $row['update'] = 'On';
+ }
+
+ // Handle all the member photos requests
+ if ($row['db_table'] == 'member_photos') {
+ // The boolean field will only be for the pending status
+ // if the data_type is boolean we know we are dealing
+ // with a newly uploaded image
+ if ($row['data_type'] == 'boolean') {
+ // No need to show any instructions for
+ // the accept/reject buttons
+ $row['update'] = 'Added';
+ }
+ }
+ if ($row['db_table'] == 'member') {
+ if ($row['field'] == 'logo') {
+ $row['update'] = 'Updated';
+ }
+ }
+ if ($row['db_table'] == 'member_files') {
+ // if the data_type is boolean we know we are dealing
+ // with a newly uploaded file
+ if ($row['data_type'] == 'boolean') {
+ // No need to show any instructions for
+ // the accept/reject buttons
+ $row['update'] = 'Added';
+ }
+ }
+ if ($row['db_table'] == 'member_packages') {
+ if ($row['field_type'] == 'file') {
+ $row['update'] = '
+ New
+
';
+ }
+ }
+ $defaults["{$row['id']}_{$row['field']}_update"] = $row['update'];
+ }
+
+ return $defaults;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ group()
+
+ /**
+ * Gets the group [table name] the field is supposed to be a part of
+ *
+ * @param string $field the name of the field in the db.
+ *
+ * @return string
+ * @access public
+ */
+ public function group($field)
+ {
+ // The field is going to come in as [id]_[field name]
+ // so we need to extract the field name from the id.
+ list($id, $field) = explode('_', $field, 2);
+ try {
+ $sql = "
+ SELECT db_table
+ FROM {$this->tableName}
+ WHERE id = :id";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $id, PDO::PARAM_INT);
+ $stmt->execute();
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+ return $row['db_table'];
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ processData()
+
+ /**
+ * Handles processing the submitted forms data.
+ *
+ * Sets up the table meta data so we can insert into the member table.
+ * removes any unwanted fields from the values array. these fields
+ * will be denoted by the '_rmv' at the end of thier name in the
+ * configureElements function
+ *
+ *
+ * ... 'name' => 'remove_rmv', ...
+ *
+ *
+ * This function also verifies that the lat/lon values were properly filled
+ * out, if they were left blank then the values will either be looked up
+ * via google maps or through our own zip DB. These values will then be
+ * inserted into the values array AND also injected into the form field
+ * values so they will display when the form comes back around.
+ *
+ * The form then decides if it is handeling a new member or not and calls
+ * the appropriate function to insert or update data.
+ *
+ * @param array $values The array of all submitted form values.
+ *
+ * @return boolean Whether the insert/update succeeded.
+ * @access protected
+ * @see Toolkit_Members_EditMemberInfo::configureElements()
+ */
+ protected function processData($values)
+ {
+ Toolkit_Common::getTableMetaData();
+
+ foreach ($values as $k => $v) {
+ switch ($k) {
+ default :
+ if (preg_match('/^.+_rmv$/', $k)) {
+ unset($values[$k]);
+ }
+ break;
+ }
+ }
+
+ $this->updateData($values);
+ $listPage = BASE_URL . "admin/members.php?cat=2&subCat=3";
+ header("Location: $listPage");
+ }
+
+ // }}}
+
+ // {{{ setMember()
+
+ /**
+ * Sets the member id to use for updating
+ *
+ * @param integer $mid Target Member Id
+ *
+ * @return object PEAR Error on invalid member id
+ * @access public
+ */
+ public function setMember($mid)
+ {
+ if (!is_numeric($mid)) {
+ return PEAR::raiseError('Invalid member id');
+ } elseif (!ctype_digit($mid) && !is_int($mid)) {
+ return PEAR::raiseError('Invalid member id string');
+ }
+ $this->_mid = $mid;
+ }
+
+ // }}}
+ // {{{ setupRenderers()
+
+ /**
+ * Handles compiling and rendering the form
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ $renderer =& new HTML_QuickForm_Renderer_Object(true);
+
+ $this->accept($renderer);
+
+ $this->template =& new HTML_Template_Flexy($this->flexyOptions);
+
+ // Make the view a copy of the $this object
+ // That way we have access to call functions in
+ // this class from within the template.
+ $this->view = $this;
+ $this->view->form = $renderer->toObject();
+ $this->template->compile($this->formTemplate);
+ }
+
+ // }}}
+
+ // {{{ toHtml()
+
+ /**
+ * Renders the form
+ *
+ * sets the page the form should be redirected to instead of coming back
+ * around to itself.
+ *
+ * @return string The rendered form
+ * @access public
+ */
+ public function toHtml()
+ {
+ // We need to validate (and freeze if needed)
+ // before we render the form. That way the
+ // template knows about any errors on the form.
+ $this->validated = $this->validate();
+
+ if ($this->validated) {
+ $processed = $this->process(
+ array(&$this, 'processData'),
+ $this->mergeFiles
+ );
+ }
+
+ // ProcessData handles settingup the lat/lon coordinates if they were
+ // not entered into the form. these values ar calculated and then
+ // inserted into the forms element values. So we need to process the
+ // data first and then render the form.
+ $this->setupRenderers();
+
+ return $this->template->bufferedOutputObject($this->view);
+ }
+
+ // }}}
+
+ // {{{ updateAmenities()
+
+ /**
+ * Handle updating any approvals or rejections on the member amenities
+ *
+ * @param array $amenities The amenity update statuses submitted from the form
+ *
+ * @return bool True on success, false on error.
+ * @access protected
+ */
+ protected function updateAmenities($amenities)
+ {
+ if (empty($amenities)) {
+ return true;
+ }
+ try {
+ $this->dbh->beginTransaction();
+ // Stmt to find the newest request in the updates table.
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE id = :id";
+
+ $fetchStmt = $this->dbh->prepare($sql);
+ // Stmt to add amenity to member.
+ $sql = "
+ INSERT INTO member_amenity(member_id, amenity_id)
+ VALUES (:member_id, :aid)";
+
+ $insStmt = $this->dbh->prepare($sql);
+ $insStmt->bindParam(':member_id', $this->_mid, PDO::PARAM_INT);
+ // Stmt to remove amenity from member.
+ $sql = "
+ DELETE FROM member_amenity
+ WHERE amenity_id = :aid";
+
+ $delStmt = $this->dbh->prepare($sql);
+ // Remove from updates table.
+ $sql = "
+ DELETE FROM {$this->tableName}
+ WHERE member_id = :member_id
+ AND db_table = 'member_amenity'
+ AND field = :aid";
+
+ $remStmt = $this->dbh->prepare($sql);
+ $remStmt->bindParam(':member_id', $this->_mid, PDO::PARAM_INT);
+ // Loop through all the amenities and see if the update was
+ // accepted or not. If it was accepted, get the update
+ // row from the updates table and find out if the update
+ // was to add [update = 1] the card or remove [update = 0].
+ // Perform the update, and then remove the requests from the
+ // updates table.
+ foreach ($amenities as $aid => $accepted) {
+ list($id, $aid) = explode('_', $aid, 2);
+ if ($accepted == 'yes') {
+ $fetchStmt->bindParam(':id', $id, PDO::PARAM_INT);
+ $fetchStmt->execute();
+ $row = $fetchStmt->fetch(PDO::FETCH_ASSOC);
+
+ if ($row['update']) {
+ // Remove the the cards from from the db to make
+ // sure we don't try to insert the same card to
+ // a member twice and conflict w/ the unique
+ // constraint on member_id and ccard_id
+ $delStmt->bindParam(':aid', $aid, PDO::PARAM_STR);
+ $delStmt->execute();
+ // Insert the card as a row into the db.
+ $insStmt->bindParam(':aid', $aid, PDO::PARAM_STR);
+ $insStmt->execute();
+ } else {
+ // Remove the the cards from from the db.
+ $delStmt->bindParam(':aid', $aid, PDO::PARAM_STR);
+ $delStmt->execute();
+ }
+
+ // Remove field from the member_updates table.
+ $remStmt->bindParam(':aid', $aid, PDO::PARAM_STR);
+ $remStmt->execute();
+ } else {
+ // Remove field from the member_updates table.
+ $remStmt->bindParam(':aid', $aid, PDO::PARAM_STR);
+ $remStmt->execute();
+ }
+ }
+ return $this->dbh->commit();
+ } catch (PDOException $e) {
+ $this->dbh->rollBack();
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ updateCCards()
+
+ /**
+ * Handle updating any approvals or rejections on the member credit cards
+ *
+ * @param array $cards The cards update status submitted from the form
+ *
+ * @return bool True on success, false on error.
+ * @access protected
+ */
+ protected function updateCCards($cards)
+ {
+ if (empty($cards)) {
+ return true;
+ }
+ foreach ($cards as $k => $v) {
+ $orig = $k;
+ list($id, $k) = explode('_', $k, 2);
+ $cards[$k] = $v;
+ unset($cards[$orig]);
+ }
+ try {
+ $this->dbh->beginTransaction();
+ // Stmt to find the newest request in the updates table.
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE id in (
+ SELECT max(id)
+ FROM {$this->tableName}
+ WHERE member_id = :member_id
+ AND field = :field)";
+
+ $fetchStmt = $this->dbh->prepare($sql);
+ $fetchStmt->bindParam(':member_id', $this->_mid, PDO::PARAM_INT);
+ // Stmt to add card to member.
+ $sql = "
+ INSERT INTO member_ccard_type (member_id, ccard_type_id)
+ SELECT :member_id, ccard_type_id
+ FROM ccard_type
+ WHERE ccard_type_name = :name";
+
+ $insStmt = $this->dbh->prepare($sql);
+ $insStmt->bindParam(':member_id', $this->_mid, PDO::PARAM_INT);
+ // Stmt to remove card from member.
+ $sql = "
+ DELETE FROM member_ccard_type
+ WHERE member_id = :member_id
+ AND ccard_type_id in (
+ SELECT ccard_type_id
+ FROM ccard_type
+ WHERE ccard_type_name = :name)";
+
+ $delStmt = $this->dbh->prepare($sql);
+ $delStmt->bindParam(':member_id', $this->_mid, PDO::PARAM_INT);
+ // Remove from updates table.
+ $sql = "
+ DELETE FROM {$this->tableName}
+ WHERE member_id = :member_id
+ AND label = :name";
+
+ $remStmt = $this->dbh->prepare($sql);
+ $remStmt->bindParam(':member_id', $this->_mid, PDO::PARAM_INT);
+ // Loop through all the cards and see if the update was
+ // accepted or not. If it was accepted, get the update
+ // row from the updates table and find out if the update
+ // was to add [update = 1] the card or remove [update = 0].
+ // Perform the update, and then remove the requests from the
+ // updates table.
+ foreach ($cards as $card => $accepted) {
+ if ($accepted == 'yes') {
+ $field = "creditCards[$card]";
+ $fetchStmt->bindParam(':field', $field, PDO::PARAM_STR);
+ $fetchStmt->execute();
+ $row = $fetchStmt->fetch(PDO::FETCH_ASSOC);
+
+ if ($row['update']) {
+ // Remove the the cards from from the db to make
+ // sure we don't try to insert the same card to
+ // a member twice and conflict w/ the unique
+ // constraint on member_id and ccard_id
+ $delStmt->bindParam(':name', $card, PDO::PARAM_STR);
+ $delStmt->execute();
+ // Insert the card as a row into the db.
+ $insStmt->bindParam(':name', $card, PDO::PARAM_STR);
+ $insStmt->execute();
+ } else {
+ // Remove the the cards from from the db.
+ $delStmt->bindParam(':name', $card, PDO::PARAM_STR);
+ $delStmt->execute();
+ }
+
+ // Remove field from the member_updates table.
+ $remStmt->bindParam(':name', $card, PDO::PARAM_STR);
+ $remStmt->execute();
+ } else {
+ // Remove field from the member_updates table.
+ $remStmt->bindParam(':name', $card, PDO::PARAM_STR);
+ $remStmt->execute();
+ }
+ }
+ return $this->dbh->commit();
+ } catch (PDOException $e) {
+ $this->dbh->rollBack();
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ updateData()
+
+ /**
+ * Handles updating all approvals and rejections of pending updates
+ *
+ * @param array $values All elements submitted from the form
+ *
+ * @return boolean True on success, false on error
+ * @access protected
+ */
+ protected function updateData($values)
+ {
+ // Credit Cards are a special case and handled seperately
+ $ccardUpdates = $values['member_ccard_type'];
+ $amenityUpdates = $values['member_amenity'];
+ $photoUpdates = $values['member_photos'];
+ $fileUpdates = $values['member_files'];
+ $packageUpdates = $values['member_packages'];
+ unset ($values['member_ccard_type'],
+ $values['member_amenity'],
+ $values['member_files'],
+ $values['member_photos'],
+ $values['member_packages']
+ );
+
+ foreach ($values as $k => $v) {
+ if (!is_array($v)) {
+ $updates[$k] = $v;
+ unset($values[$k]);
+ }
+ }
+ // The values array should now hold all the submitted updates
+ // in a grouped format and tell you if the field was approved
+ // to be updated or not. Fields from each table will be grouped
+ // together and any text field that "could" be changed by the
+ // admin to fix typos or errors will be in thier own array.
+ // These updates will have the same associative array key name
+ // as thier corresponding field with '_update' appended.
+ // ie. street => street_update, url => url_update, etc..
+ // (values example:)
+ // Array
+ // (
+ // [member] => Array
+ // (
+ // [street] => yes
+ // [url] => no
+ // [description] => yes
+ // )
+ //
+ // [member_accommodations] => Array
+ // (
+ // [num_rooms] => yes
+ // [year_round] => no
+ // )
+ //
+ // [member_restaurants] => Array
+ // (
+ // [breakfast] => yes
+ // )
+ // )
+ // (updates example:)
+ // Array
+ // (
+ // [street_update] => 139 Dove Cottage Ln
+ // [url_update] => www.google.com
+ // [description_update] => test update 8
+ // )
+
+ try {
+ // Remove from updates table.
+ $sql = "
+ DELETE FROM {$this->tableName}
+ WHERE member_id = :member_id
+ AND field = :field
+ AND db_table = :db_table";
+
+ $remStmt = $this->dbh->prepare($sql);
+ $remStmt->bindParam(':member_id', $this->_mid, PDO::PARAM_INT);
+ // For each of the "rejected" updates, loop through
+ // and remove them from the arrays as well as from the
+ // updates DB table.
+
+ // Tables
+ foreach ($values as $table => &$fields) {
+ // Fields
+ //
+ // The field key names will come in as
+ // [id_fieldName] => yes
+ // [id_fieldName] => no
+ // The id # is the primary key row id number of the update
+ // in the updates table.
+ // The fieldName is the name of column that was updated.
+ foreach ($fields as $k => &$v) {
+ if ($v == 'no') {
+ list($id, $field) = explode('_', $k, 2);
+ $remStmt->bindParam(':field', $field, PDO::PARAM_STR);
+ $remStmt->bindParam(':db_table', $table, PDO::PARAM_STR);
+ $remStmt->execute();
+ unset($fields["{$id}_{$field}"],
+ $updates["{$id}_{$field}_update"]);
+ }
+ }
+ // Do some cleanup while we're right here.
+ // If all the updates were rejected for a single group,
+ // then unset this array, that way we won't waste our time
+ // trying to run updates against it later.
+ if (empty($values[$table])) {
+ unset($values[$table]);
+ }
+ }
+
+ foreach ($values as $k => &$v) {
+ if (!is_array($updates)) {
+ $updates = array();
+ }
+ $this->commitUpdates($k, array_keys($v), $updates);
+ }
+ $this->updatePackages($packageUpdates);
+ $this->updateCCards($ccardUpdates);
+ $this->updateAmenities($amenityUpdates);
+ $this->updatePhotos($photoUpdates);
+ $this->updateFiles($fileUpdates);
+ } catch (PDOException $e) {
+ $this->dbh->rollBack();
+ return Toolkit_Common::handleError($e);
+ }
+ return true;
+ }
+
+ // }}}
+ // {{{ updateFiles()
+
+ /**
+ * Handle updating any approvals or rejections on the member files
+ *
+ * @param array $files an array of file updates and their update status
+ *
+ * @return bool True on success, false on error.
+ * @access protected
+ */
+ protected function updateFiles($files)
+ {
+ if (empty($files)) {
+ return true;
+ }
+ try {
+ $this->dbh->beginTransaction();
+ // Stmt to find the newest request in the updates table for
+ // a specific field.
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE id = :id";
+
+ $fetchStmt = $this->dbh->prepare($sql);
+ // Stmt to update the file
+ $updateSql = "
+ UPDATE member_files
+ SET %s = :update
+ WHERE id = :id";
+ // Stmt to remove file from member.
+ $sql = "
+ DELETE FROM member_files
+ WHERE id = :id";
+
+ $delStmt = $this->dbh->prepare($sql);
+ // Stmt to remove any file name updates for a file that
+ // are still in the updates table.
+ $sql = "
+ DELETE FROM {$this->tableName}
+ WHERE field = 'file_name'
+ AND foreign_key = :id";
+
+ $delFileNameStmt = $this->dbh->prepare($sql);
+ // Remove from updates table.
+ $sql = "
+ DELETE FROM {$this->tableName}
+ WHERE field = :field
+ AND foreign_key = :id";
+
+ $remStmt = $this->dbh->prepare($sql);
+ // Loop through all the files and see if the update was
+ // accepted or not. If it was accepted, get the update
+ // row from the updates table and find out if the update
+ // was to add [update = 1] the card or remove [update = 0].
+ // Perform the update, and then remove the requests from the
+ // updates table.
+ foreach ($files as $field => $accepted) {
+ list($id, $field) = explode('_', $field, 2);
+ $fetchStmt->bindParam(':id', $id, PDO::PARAM_INT);
+ $fetchStmt->execute();
+ $row = $fetchStmt->fetch(PDO::FETCH_ASSOC);
+
+ if ($accepted == 'yes') {
+ $updtStmt = $this->dbh->prepare(sprintf($updateSql, $field));
+ // we are dealing w/ the file_name
+ // update the files name.
+ $updtStmt->bindParam(':update', $row['update'], PDO::PARAM_STR);
+ $updtStmt->bindParam(':id', $row['foreign_key'], PDO::PARAM_INT);
+ $updtStmt->execute();
+
+ // Remove field from the member_updates table.
+ $remStmt->bindParam(':field', $field, PDO::PARAM_STR);
+ $remStmt->bindParam(':id', $row['foreign_key'], PDO::PARAM_INT);
+ $remStmt->execute();
+ } else {
+ // Remove field from the member_updates table.
+ $remStmt->bindParam(':field', $field, PDO::PARAM_STR);
+ $remStmt->bindParam(':id', $row['foreign_key'], PDO::PARAM_INT);
+ $remStmt->execute();
+
+ // a rejected file (we know its a file because it
+ // has a data_type of boolean) means we have to not only
+ // remove the row from the updates table, but also
+ // from the member_files table.
+ if ($row['data_type'] == 'boolean') {
+ $delFileNameStmt->bindParam(
+ ':id',
+ $row['foreign_key'],
+ PDO::PARAM_STR
+ );
+ $delFileNameStmt->execute();
+
+ // Remove the the cards from from the db.
+ $delStmt->bindParam(
+ ':id',
+ $row['foreign_key'],
+ PDO::PARAM_INT
+ );
+ $delStmt->execute();
+ }
+ }
+ }
+ return $this->dbh->commit();
+ } catch (PDOException $e) {
+ $this->dbh->rollBack();
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ updatePackages()
+
+ /**
+ * Handle updating any approvals or rejections on the member packages
+ *
+ * @param array $packages an array of package updates and their update status
+ *
+ * @return bool True on success, false on error.
+ * @access protected
+ */
+ protected function updatePackages($packages)
+ {
+ if (empty($packages)) {
+ return true;
+ }
+ try {
+ $this->dbh->beginTransaction();
+ // Stmt to find the newest request in the updates table for
+ // a specific field.
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE id = :id";
+
+ $fetchStmt = $this->dbh->prepare($sql);
+ // Stmt to update the package
+ $updateSql = "
+ UPDATE member_packages
+ SET %s = :update
+ WHERE id = :id";
+ // Stmt to remove any updates for a package that
+ // are still in the updates table.
+ // Remove from updates table.
+ $sql = "
+ DELETE FROM {$this->tableName}
+ WHERE foreign_key = :id
+ AND field = :field
+ AND db_table = 'member_packages'";
+
+ $remStmt = $this->dbh->prepare($sql);
+ // Loop through all the package field and see if the update was
+ // accepted or not. If it was accepted, get the update
+ // row from the updates table and find out if the update
+ // was to add [update = 1] the card or remove [update = 0].
+ // Perform the update, and then remove the requests from the
+ // updates table.
+ foreach ($packages as $field => $accepted) {
+ list($id, $field) = explode('_', $field, 2);
+ $fetchStmt->bindParam(':id', $id, PDO::PARAM_INT);
+ $fetchStmt->execute();
+ $row = $fetchStmt->fetch(PDO::FETCH_ASSOC);
+
+ if ($accepted == 'yes') {
+ $updtStmt = $this->dbh->prepare(sprintf($updateSql, $field));
+ $update = $this->getSubmitValue("{$id}_{$field}_update");
+ if (empty($update)) {
+ $update = $row['update'];
+ }
+ $updtStmt->bindParam(':update', $update, PDO::PARAM_STR);
+ $updtStmt->bindParam(':id', $row['foreign_key'], PDO::PARAM_INT);
+ $updtStmt->execute();
+
+ // Remove field from the member_updates table.
+ $remStmt->bindParam(':field', $field, PDO::PARAM_STR);
+ $remStmt->bindParam(':id', $row['foreign_key'], PDO::PARAM_INT);
+ $remStmt->execute();
+ } else {
+ // Remove field from the member_updates table.
+ $remStmt->bindParam(':field', $field, PDO::PARAM_STR);
+ $remStmt->bindParam(':id', $row['foreign_key'], PDO::PARAM_INT);
+ $remStmt->execute();
+ }
+ }
+ return $this->dbh->commit();
+ } catch (PDOException $e) {
+ $this->dbh->rollBack();
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ updatePhotos()
+
+ /**
+ * Handle updating any approvals or rejections on the member photos
+ *
+ * @param array $photos an array of photo updates and thier update status
+ *
+ * @return bool True on success, false on error.
+ * @access protected
+ */
+ protected function updatePhotos($photos)
+ {
+ if (empty($photos)) {
+ return true;
+ }
+ try {
+ $this->dbh->beginTransaction();
+ // Stmt to find the newest request in the updates table for
+ // a specific field.
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE id = :id";
+
+ $fetchStmt = $this->dbh->prepare($sql);
+ // Stmt to update the photo
+ $updateSql = "
+ UPDATE member_photos
+ SET %s = :update
+ WHERE id = :id";
+ // Stmt to remove photo from member.
+ $sql = "
+ DELETE FROM member_photos
+ WHERE id = :id";
+
+ $delStmt = $this->dbh->prepare($sql);
+ // Stmt to remove any caption updates for a photo that
+ // are still in the updates table.
+ $sql = "
+ DELETE FROM {$this->tableName}
+ WHERE field = 'caption'
+ AND foreign_key = :id";
+
+ $delPhotoCaptionStmt = $this->dbh->prepare($sql);
+ // Remove from updates table.
+ $sql = "
+ DELETE FROM {$this->tableName}
+ WHERE foreign_key = :id
+ AND field = :field";
+
+ $remStmt = $this->dbh->prepare($sql);
+ // Loop through all the photos and see if the update was
+ // accepted or not. If it was accepted, get the update
+ // row from the updates table and find out if the update
+ // was to add [update = 1] the card or remove [update = 0].
+ // Perform the update, and then remove the requests from the
+ // updates table.
+ foreach ($photos as $field => $accepted) {
+ list($id, $field) = explode('_', $field, 2);
+ $fetchStmt->bindParam(':id', $id, PDO::PARAM_INT);
+ $fetchStmt->execute();
+ $row = $fetchStmt->fetch(PDO::FETCH_ASSOC);
+
+ if ($accepted == 'yes') {
+ $updtStmt = $this->dbh->prepare(sprintf($updateSql, $field));
+ // we are dealing w/ the caption
+ // update the photos caption.
+ $updtStmt->bindParam(':update', $row['update'], PDO::PARAM_STR);
+ $updtStmt->bindParam(':id', $row['foreign_key'], PDO::PARAM_INT);
+ $updtStmt->execute();
+
+ // Remove field from the member_updates table.
+ $remStmt->bindParam(':field', $field, PDO::PARAM_STR);
+ $remStmt->bindParam(':id', $row['foreign_key'], PDO::PARAM_INT);
+ $remStmt->execute();
+ } else {
+ // Remove field from the member_updates table.
+ $remStmt->bindParam(':field', $field, PDO::PARAM_STR);
+ $remStmt->bindParam(':id', $row['foreign_key'], PDO::PARAM_INT);
+ $remStmt->execute();
+
+ // a rejected photo (we know its a photo because it
+ // has a data_type of boolean) means we have to not only
+ // remove the row from the updates table, but also
+ // from the member_photos table.
+ if ($row['data_type'] == 'boolean') {
+ $delPhotoCaptionStmt->bindParam(
+ ':id',
+ $row['foreign_key'],
+ PDO::PARAM_STR
+ );
+ $delPhotoCaptionStmt->execute();
+
+ // Remove the the cards from from the db.
+ $delStmt->bindParam(
+ ':id',
+ $row['foreign_key'],
+ PDO::PARAM_INT
+ );
+ $delStmt->execute();
+ }
+ }
+ }
+ return $this->dbh->commit();
+ } catch (PDOException $e) {
+ $this->dbh->rollBack();
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ validated()
+
+ /**
+ * Checks if the form is validated
+ *
+ * If the form is validated display the success msg.
+ * If the form is submitted but not validated, display
+ * the error msg. Other wise display nothing.
+ *
+ * This function is called from within the template.
+ *
+ * @return string The success or error msg for the user.
+ * @access protected
+ */
+ public function validated()
+ {
+ if ($this->validated) {
+ return $this->successMsg;
+ } elseif ($this->isSubmitted()) {
+ return $this->errorMsg;
+ }
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/Admin/Auxiliary.php b/Toolkit/Members/Admin/Auxiliary.php
new file mode 100644
index 0000000..96b1a6c
--- /dev/null
+++ b/Toolkit/Members/Admin/Auxiliary.php
@@ -0,0 +1,509 @@
+
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: Auxiliary.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Base class used for building forms to accompany the members database
+ *
+ * This class handles all common functions that are to be used in
+ * the auxiliary forms used to assist in the members DB.
+ * (categories, amenities, regions, etc...).
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit_Members, member_admin
+ */
+abstract class Toolkit_Members_Admin_Auxiliary extends Toolkit_FormBuilder
+{
+ // {{{ properties
+
+ /**
+ * Primary table used for database calls
+ *
+ * @var string
+ * @access public
+ */
+ public $tableName;
+
+ /**
+ * Array of primary table meta data
+ *
+ * This array will hold the column data types for the fields
+ * that will be manipulated in the database.
+ *
+ * @var array
+ * @access public
+ * @see Toolkit_Common::getTableMetaData()
+ */
+ public $tableMetaData;
+
+ /**
+ * The name of the template used for the form
+ *
+ * @var string
+ * @access protected
+ */
+ protected $formTemplate;
+
+ /**
+ * The object to use inside the form
+ *
+ * This object which is to be populated by the $this object
+ * is used inside the templates and allows access back into the
+ * calling class to call publicly available functions
+ *
+ * @var string
+ * @access protected
+ */
+ protected $view;
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Class constructor
+ *
+ * @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(
+ $formName,
+ $method = 'post',
+ $action = '',
+ $target = '',
+ $attributes = null,
+ $trackSubmit = false
+ ) {
+ parent::__construct(
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+ $this->registeredRules = array();
+
+ $this->configureElements();
+ $this->configureRules();
+ $this->configureFilters();
+ $this->configureDefaults();
+
+ $this->flexyOptions = Toolkit_Members::getFlexyOptions();
+ }
+
+ // }}}
+
+ // {{{ baseUrl()
+
+ /**
+ * Returns the BASE_URL
+ *
+ * This function is used inside the Flexy Templated forms
+ *
+ * @return string BASE_URL
+ * @access public
+ */
+ public function baseUrl()
+ {
+ return BASE_URL;
+ }
+
+ // }}}
+
+ // {{{ configureDefaults()
+
+ /**
+ * Configure the default values for the form
+ *
+ * Since each form is different, you will need to redefine this
+ * method inside of each subclass and create your own rules
+ * based on your forms elements.
+ *
+ * @return void
+ * @access public
+ */
+ abstract protected function configureDefaults();
+
+ // }}}
+ // {{{ configureElements()
+
+ /**
+ * Configures all form elements
+ *
+ * If you are subclassing this base class out, you will need to define
+ * all your forms elements in your new subclass.
+ *
+ * @return void
+ * @access protected
+ */
+ abstract protected function configureElements();
+
+ // }}}
+ // {{{ configureFilters()
+
+ /**
+ * Defines all filters used on form elements when submitted
+ *
+ * Most times this function won't need to be overridden.
+ *
+ * @return void
+ * @access public
+ */
+ protected function configureFilters()
+ {
+ $filters[] = array('element' => '__ALL__', 'filter' => 'trim');
+
+ $this->setupFilters($filters);
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Sets up the required / not-required rules for forms
+ *
+ * At the bare minimum, the required / not-required rules for form
+ * needs to be defined. Since these rules are most easily defined
+ * while creating the element definitions themselves the base function
+ * is to call the setupRules function that will instantiate these
+ * rules in the quickform class.
+ *
+ * @return void
+ * @access public
+ */
+ protected function configureRules()
+ {
+ $this->setupRules();
+ }
+
+ // }}}
+
+ // {{{ getSetParameters()
+
+ /**
+ * get a string of sql query parameters
+ *
+ * @param array $values parameters to include
+ *
+ * @return string sql query parameters
+ * @access protected
+ */
+ protected function getSetParameters($values)
+ {
+ $params = array_keys($values);
+ $length = count($params);
+ for ($i = 0; $i < $length; ++$i) {
+ $bindParams .= "{$params[$i]} = :{$params[$i]}";
+ if ($i < ($length - 1)) {
+ $bindParams .= ', ';
+ }
+ }
+ return $bindParams;
+ }
+
+ // }}}
+ // {{{ getDataType()
+
+ /**
+ * gets the datatype of the element
+ *
+ * @param string $k name of element
+ *
+ * @return string datatype
+ * @access protected
+ */
+ protected function getDataType($k)
+ {
+ $metaData = $this->tableMetaData[$k];
+ if ($metaData == 'integer') {
+ return PDO::PARAM_INT;
+ } else if ($metaData == 'boolean') {
+ return PDO::PARAM_BOOL;
+ } elseif ($metaData == 'double precision') {
+ return null;
+ } else {
+ return PDO::PARAM_STR;
+ }
+ }
+
+ // }}}
+
+ // {{{ insertData()
+
+ /**
+ * insert the data in the DB
+ *
+ * @param array $values Submitted form values
+ * @param string $sql Query to execute to make update
+ *
+ * @return void
+ * @access protected
+ */
+ protected function insertData($values, $sql)
+ {
+ try {
+ $stmt = $this->dbh->prepare($sql);
+ foreach ($values as $k => $v) {
+ $dataType = $this->getDataType($k);
+ $stmt->bindParam(":$k", $values[$k], $dataType);
+ }
+ return $stmt->execute();
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ isEdit()
+
+ /**
+ * Determines if we are editing an object or not
+ *
+ * If we are ever editing an object, member, category, city, etc...
+ * There will be the objects DB ID passed along in the url under the
+ * id key. If we can find this then we know we're editing, if not
+ * then we are adding.
+ *
+ * @return void
+ * @access public
+ */
+ public function isEdit()
+ {
+ return isset($_GET['id']);
+ }
+
+ // }}}
+
+ // {{{ processData()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param array $values Parameter description (if any) ...
+ *
+ * @return array Return description (if any) ...
+ * @access protected
+ */
+ protected function processData($values)
+ {
+ Toolkit_Common::getTableMetaData();
+
+ foreach ($values as $k => $v) {
+ switch ($k) {
+ case 'uploaded_file_rmv' :
+ // Don't remove this from the values array.
+ // we will handle it later.
+ // we need to have access to this value
+ // in the insert/update functions.
+ break;
+
+ case 'MAX_FILE_SIZE' :
+ unset($values[$k]);
+ break;
+
+ default :
+ if (preg_match('/^.+_rmv$/', $k)) {
+ unset($values[$k]);
+ }
+ break;
+ }
+ }
+
+ if (isset($_GET['id'])) {
+ return $this->updateData($values);
+ } else {
+ return $this->insertData($values);
+ }
+ }
+
+ // }}}
+
+ // {{{ setupElements()
+
+ /**
+ * Add the form elements defined in your class to a QuickForm
+ *
+ * Handles adding singleton elements as well as grouped elements.
+ * If added elements fail to correctly add to the form, the script
+ * should die gracefully, telling the user there was a problem.
+ *
+ * @param array $elements form element definitions
+ *
+ * @throws HTML_QuickForm_Error error raised from QuickForm class.
+ * @return void
+ * @access protected
+ */
+ protected function setupElements($elements)
+ {
+ $this->formElements = $elements;
+ foreach ($elements as $e) {
+ if ($e['type'] != 'group') {
+ try {
+ $source =& $this->addElement($e['type'], $e['name'], $e['display'], $e['opts'], $e['att'], $e['val']);
+ } catch (HTML_QuickForm_Error $e) {
+ Toolkit_Common::dieGracefully(null, $e);
+ }
+ if ($e['type'] == 'advmultiselect') {
+ $source->setLabel($e['labels']);
+ }
+ if ($e['name'] == 'categories') {
+ $res = $source->loadArray($this->categories);
+ if (PEAR::isError($res)) {
+ Toolkit_Common::dieGracefully(null, $res);
+ }
+ }
+ if ($e['type'] == 'header') {
+ $this->formHeaders[$e['display']] = $e;
+ }
+ } elseif (is_array($e['group'])) {
+ unset($field);
+ foreach ($e['group'] as $g) {
+ $field[] =& HTML_QuickForm::createElement($g['type'], $g['name'], $g['display'], $g['opts'], $g['att'], $g['val']);
+ }
+ $source =& $this->addGroup($field, $e['name'], $e['label'], $e['seperator'], $e['appendName']);
+ }
+ }
+ }
+
+ // }}}
+ // {{{ setupRenderers()
+
+ /**
+ * Sets up the rendering engine for the form
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ $renderer =& new HTML_QuickForm_Renderer_Object(true);
+
+ $this->accept($renderer);
+
+ $this->template =& new HTML_Template_Flexy($this->flexyOptions);
+
+ // Make the view a copy of the $this object
+ // That way we have access to call functions in
+ // this class from within the template.
+ $this->view = $this;
+ $this->view->form = $renderer->toObject();
+ $this->template->compile($this->formTemplate);
+ }
+
+ // }}}
+
+ // {{{ toHTML()
+
+ /**
+ * Renders the form for viewing
+ *
+ * This function validates the form if needed, and if it successfully
+ * validates attempts to insert or update the data record.
+ * If it is unsuccessful, it will return an error to the user
+ * informing them of what went wrong.
+ *
+ * @param string $listPage The page the header should redirect
+ * to on successful insert or update.
+ *
+ * @return string The compiled and filled form template.
+ * @access public
+ */
+ public function toHTML($listPage = 'index.php')
+ {
+ // We need to validate (and freeze if needed)
+ // before we render the form. That way the
+ // template knows about any errors on the form.
+ $this->validated = $this->validate();
+ $this->setupRenderers();
+
+ if ($this->validated) {
+ $processed = $this->process(
+ array(&$this, 'processData'),
+ $this->mergeFiles
+ );
+ if ($processed) {
+ header("Location: $listPage");
+ } else {
+ $errorMsg = "There was an unexpected error. Please try again later.";
+ }
+ }
+
+ return $errorMsg . $this->template->bufferedOutputObject($this->view);
+ }
+
+ // }}}
+
+ // {{{ updateData()
+
+ /**
+ * update the data in the DB
+ *
+ * @param array $values Submitted form values
+ * @param string $sql Query to execute to make update
+ *
+ * @return boolean result of query
+ * @access protected
+ */
+ protected function updateData($values, $sql)
+ {
+ try {
+ $stmt = $this->dbh->prepare($sql);
+ foreach ($values as $k => &$v) {
+ $dataType = $this->getDataType($k);
+ $stmt->bindParam(":$k", $v, $dataType);
+ }
+ return $stmt->execute();
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ validated()
+
+ /**
+ * Returns form message from validation attempts
+ *
+ * @return string validation message
+ * @access public
+ */
+ public function validated()
+ {
+ if ($this->validated) {
+ return $this->successMsg;
+ } elseif ($this->isSubmitted()) {
+ return $this->errorMsg;
+ }
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/Admin/Controller.php b/Toolkit/Members/Admin/Controller.php
new file mode 100755
index 0000000..546681b
--- /dev/null
+++ b/Toolkit/Members/Admin/Controller.php
@@ -0,0 +1,1081 @@
+
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: Controller.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ * @see HTML_Menu
+ * @see HTML_Menu_DirectRenderer
+ */
+
+require_once 'HTML/Menu.php';
+
+/**
+ * Description for require_once
+ */
+require_once 'HTML/Menu/DirectRenderer.php';
+
+/**
+ * Description for require_once
+ */
+require_once 'Members/Admin/Search.php';
+
+/**
+ * Handles calling the appropriate functionality for admin
+ *
+ * Controls prepping the functions/classes/objects that will be used
+ * to populate the page when a user clicks through the nav/subnav structure
+ * within the members admin area.
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Members_Admin_Controller
+{
+ // {{{ properties
+
+ /**
+ * Structure of the members main navigation
+ * @var array
+ * @access public
+ */
+ public $navStructure = array();
+
+ /**
+ * Which module to load into the page
+ *
+ * EditMember, EditCity, etc...
+ *
+ * @var unknown
+ * @access public
+ */
+ public $pageModule;
+
+ /**
+ * How to render the base page layout
+ * @var string
+ * @access private
+ */
+ private $_template = 'admin.tpl';
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * Handle some essential setup procedures
+ *
+ * @param PDO $pdo PHP Data Object to use for DB calls
+ * @param Config_Container $c Configuration object
+ *
+ * @return void
+ * @access public
+ */
+ public function __construct(PDO $pdo, Config_Container $c)
+ {
+ $this->dbh = $pdo;
+ $this->config = $c;
+ }
+
+ // }}}
+
+ // {{{ addMember()
+
+ /**
+ * Call the module to handle adding a new member
+ *
+ * @return string New member form
+ * @access protected
+ */
+ protected function addMember()
+ {
+ $member =& new Toolkit_Members();
+ return $member->toHtml();
+ }
+
+ // }}}
+ // {{{ amenityScriptsAndStyles()
+
+ /**
+ * Set the styles and scripts for the amenity pages
+ *
+ * @param array &$scripts array for scripts on the page
+ * @param array &$styles array for styles on the page
+ *
+ * @return void
+ * @access protected
+ */
+ protected function amenityScriptsAndStyles(
+ array &$scripts,
+ array &$styles
+ ) {
+ switch ($_GET['subCat']) {
+ case 2 :
+ $scripts[] = BASE_URL . 'Toolkit/Members/libjs/edit-amenity.js';
+ break;
+
+ default :
+ break;
+ }
+ }
+
+ // }}}
+ // {{{ authorizeNewRequests()
+
+ /**
+ * Call the module to authorize new member requests submitted from the front end
+ *
+ * @return string New member authorization form
+ * @access protected
+ */
+ protected function authorizeNewRequests()
+ {
+ $form = new Toolkit_Members_Admin_AuthorizeNewMemberForm('authorize_form');
+ return $form->toHTML();
+ }
+
+ // }}}
+ // {{{ authorizeUpdates()
+
+ /**
+ * Call the module to authorize any new changes made by members
+ *
+ * @return string Authorization form for member updates
+ * @access protected
+ */
+ protected function authorizeUpdates()
+ {
+ $updateForm =& new Toolkit_Members_Admin_AuthorizeUpdates($this->dbh, 'auth_updates');
+ $updateForm->setMember($_GET['id']);
+ $updateForm->configureForm();
+ return $updateForm->toHtml();
+ }
+
+ // }}}
+
+ // {{{ categoryScriptsAndStyles()
+
+ /**
+ * Set the styles and scripts for the category pages
+ *
+ * @param array &$scripts array for scripts on the page
+ * @param array &$styles array for styles on the page
+ *
+ * @return void
+ * @access protected
+ */
+ protected function categoryScriptsAndStyles(
+ array &$scripts,
+ array &$styles
+ ) {
+ switch ($_GET['subCat']) {
+ // List Categories
+ case 1 :
+ default :
+ $styles[] = GLM_APP_BASE_URL . 'libjs/jsTree/source/tree_component.css';
+ $scripts[] = GLM_APP_BASE_URL . 'libjs/jsTree/libjs/css.js';
+ $scripts[] = GLM_APP_BASE_URL . 'libjs/jquery.listen.js';
+ $scripts[] = GLM_APP_BASE_URL . 'libjs/jsTree/source/tree_component.js';
+ $scripts[] = GLM_APP_BASE_URL . 'libjs/jquery.cookie.js';
+ $scripts[] = BASE_URL . 'Toolkit/Members/libjs/list-categories.js';
+ break;
+
+ // Edit Category
+ case 2 :
+ $scripts[] = BASE_URL . 'Toolkit/Members/libjs/edit-category.js';
+ break;
+ }
+ }
+
+ // }}}
+ // {{{ cityScriptsAndStyles()
+
+ /**
+ * Set the styles and scripts for the city pages
+ *
+ * @param array &$scripts array for scripts on the page
+ * @param array &$styles array for styles on the page
+ *
+ * @return void
+ * @access protected
+ */
+ protected function cityScriptsAndStyles(
+ array &$scripts,
+ array &$styles
+ ) {
+ switch ($_GET['subCat']) {
+ case 2 :
+ $scripts[] = BASE_URL . 'fckeditor/fckeditor.js';
+ $scripts[] = BASE_URL . 'Toolkit/Members/libjs/edit-city.js';
+ break;
+
+ default :
+ break;
+ }
+ }
+
+ // }}}
+
+ // {{{ editAmenity()
+
+ /**
+ * Call the module to handle editing a members amenities
+ *
+ * @return string Amenity editing form
+ * @access protected
+ */
+ protected function editAmenity()
+ {
+ $form = new Toolkit_Members_Admin_EditAmenity($this->dbh,
+ 'edit_amenity');
+ $form->configureForm();
+ return $form->toHtml();
+ }
+
+ // }}}
+ // {{{ editCategory()
+
+ /**
+ * Call the module to handle adding/editing/deleting categories
+ *
+ * @return string Category editing form
+ * @access protected
+ */
+ protected function editCategory()
+ {
+ $form = new Toolkit_Members_Admin_EditCategory($this->dbh,
+ 'edit_category');
+ $form->configureForm();
+ return $form->toHtml();
+ }
+
+ // }}}
+ // {{{ editCity()
+
+ /**
+ * Call the module to handle editing the cities allowed for members
+ *
+ * @return string City editing form
+ * @access protected
+ */
+ protected function editCity()
+ {
+ $form =& new Toolkit_Members_Admin_EditCity($this->dbh,
+ 'edit_city');
+ $form->setImageServer(new Toolkit_Image_Server());
+ $form->configureForm($this->config);
+ return $form->toHtml();
+ }
+
+ // }}}
+ // {{{ editCounty()
+
+ /**
+ * Call the module to handle editing the counties allowed for members
+ *
+ * @return string County editing form
+ * @access protected
+ */
+ protected function editCounty()
+ {
+ die('not finished');
+ $form =& new Toolkit_Members_Admin_EditCounty($this->dbh,
+ 'edit_city');
+ $form->configureForm();
+ return $form->toHtml();
+ }
+
+ // }}}
+ // {{{ editHtmlEmail()
+
+ /**
+ * Call the module to handle editing the counties allowed for members
+ *
+ * @return string County editing form
+ * @access protected
+ */
+ protected function editHtmlEmail()
+ {
+ $form =& new Toolkit_Members_Admin_EditHtmlEmail($this->dbh,
+ 'edit_html_email');
+ $form->configureForm();
+ return $form->toHtml();
+ }
+
+ // }}}
+ // {{{ editRegion()
+
+ /**
+ * Call the module to handle editing the regions allowed for members
+ *
+ * @return string Region editing form
+ * @access protected
+ */
+ protected function editRegion()
+ {
+ $form =& new Toolkit_Members_Admin_EditRegion($this->dbh,
+ 'edit_region');
+ $form->configureForm();
+ return $form->toHtml();
+ }
+
+ // }}}
+
+ // {{{ getPageModule()
+
+ /**
+ * Retrieve the module we are going to need for the page
+ *
+ * Page modules are defined in the navigation structure
+ *
+ * @return void
+ * @access public
+ */
+ public function getPageModule()
+ {
+ $default = 'homePage';
+ $moduleId = $_GET['cat'] . $_GET['subCat'];
+ /*
+ if (!is_numeric($moduleId)) {
+ return false;
+ }
+ // Make sure the category id exists.
+ if (!array_key_exists($_GET['cat'], $this->navStructure)) {
+ return false;
+ }
+ // Make sure the page sub category id exists.
+ if (is_numeric($_GET['subCat']) &&
+ !array_key_exists($moduleId, $this->navStructure[$_GET['cat']]['sub'])) {
+ return false;
+ }
+ */
+
+ if (!is_numeric($_GET['subCat'])) {
+ $function = $this->navStructure[$_GET['cat']]['module'];
+ } else {
+ $function = $this->navStructure[$_GET['cat']]['sub'][$moduleId]['module'];
+ }
+
+ $this->pageModule = isset($function) ? $function : $default;
+ }
+
+ // }}}
+ // {{{ _getPageNav()
+
+ /**
+ * Render the page navigation that is defined in the navStructure
+ *
+ * @return string Page navigation structure
+ * @access private
+ */
+ private function _getPageNav()
+ {
+ $menu =& new HTML_Menu($this->navStructure, 'rows');
+
+ // Default nav index is Home which is at index 1.
+ $currIndex = 1;
+
+ // If we are on another category id, set that
+ // category id as the nav index we are on.
+ if (is_numeric($_GET['cat'])) {
+ $currIndex = $_GET['cat'];
+ }
+ // If we are looking at a subPage, then append
+ // that subPages id # to the navIndex.
+ if (is_numeric($_GET['subCat'])) {
+ $currIndex .= $_GET['subCat'];
+ }
+
+ // Set which category id we are currently looking at.
+ $menu->forceCurrentIndex($currIndex);
+
+ $rEngine =& new HTML_Menu_DirectRenderer($tpl);
+ $rEngine->setEntryTemplate(HTML_MENU_ENTRY_INACTIVE, '
';
+ $renderer->setElementTemplate($tpl, 'submit');
+ }
+
+ // @codeCoverageIgnoreEnd
+ // }}}
+
+ // {{{ toHtml()
+
+ /**
+ * Call the rendering function to get the form in a string
+ *
+ * @access protected
+ * @return string $output The Form to be rendered or success msg.
+ */
+ public function toHtml()
+ {
+ $this->setupRenderers();
+ if ($this->validate()) {
+ $output = parent::toHTML();
+ } elseif ($this->isSubmitted()) {
+ $output = $this->errorMsg;
+ $output .= parent::toHTML();
+ } else {
+ $output = parent::toHTML();
+ }
+ return $output;
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/Auth.php b/Toolkit/Members/Auth.php
new file mode 100644
index 0000000..639b495
--- /dev/null
+++ b/Toolkit/Members/Auth.php
@@ -0,0 +1,802 @@
+
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: Auth.php,v 1.2 2009/12/15 20:18:15 jamie Exp $
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit_Members_Auth-LoginForm, Toolkit_Members_Auth-PasswordForm
+ */
+
+require_once 'Auth.php';
+
+/**
+ * Methods for the memberdb authentication system
+ *
+ * Handles Cookie and session generation, id challenges and security for
+ * the memberdb application
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit_Members_Auth-LoginForm, Toolkit_Members_Auth-PasswordForm
+ */
+class Toolkit_Members_Auth extends Auth
+{
+ // {{{ properties
+
+ /**
+ * Maximum idle time
+ *
+ * If more seconds pass before a new page request, then the user
+ * will have to re-authenticate back into the application.
+ * 1800 = 30 min
+ * 3600 = 1 hr
+ *
+ * @var integer
+ * @access protected
+ */
+ protected $idleTime = 1800;
+
+ /**
+ * Authentication options for storage driver
+ *
+ * This is setup here, so it can be overridden in subclasses and merged
+ * into existing authentication options.
+ *
+ * @var array
+ * @access protected
+ */
+ protected $classOptions = array();
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * Sets up the storage driver
+ *
+ * @param Config_Container $c Configuration object
+ * @param string $storageDriver (optional)Type of the storage
+ * driver
+ * @param array $options (optional)Additional options
+ * for the storage driver
+ * @param string $loginFunction (optional)Name of the function
+ * that creates the login form
+ * @param boolean $showLogin (optional)Should the login form
+ * be displayed if neccessary?
+ *
+ * @return void
+ * @access public
+ */
+ public function __construct(
+ Config_Container $c,
+ $storageDriver = 'DB',
+ array $options = array(),
+ $loginFunction = '',
+ $showLogin = true
+ ) {
+ $this->config = $c;
+ // These are the default options, they are defined here b/c
+ // constants cannot be defined in the properites.
+ // subclasses that define any of the same authOptions will overwrite
+ // these when the options are merged. ALSO, options passed in
+ // via parameters will supercede/overwrite any of these authOptions
+ // or subclass authOptions.
+ $defaultOptions = array(
+ 'dsn' => DSN,
+ 'table' => 'member',
+ 'usernamecol' => 'member_login',
+ 'passwordcol' => 'member_passwd',
+ 'db_fields' => array('member_id', 'member_name'),
+ 'cryptType' => 'none',
+ 'db_where' => 'new_member != true',
+ );
+
+ $authOptions = array_merge(
+ $defaultOptions,
+ $this->classOptions,
+ $options
+ );
+
+ parent::Auth($storageDriver, $authOptions, $loginFunction, $showLogin);
+ }
+
+ // }}}
+
+ // {{{ loginForm()
+
+ /**
+ * Function to set up the regular login form
+ *
+ * @param unknown $uname Last attempted username
+ * @param unknown $status The authorization status
+ * @param unknown &$auth The authentication object
+ *
+ * @return void
+ * @access public
+ */
+ protected function loginForm($uname = null, $status = null, &$auth = null)
+ {
+ $login =& new LoginForm('member_login',
+ 'post',
+ BASE_URL . 'memberdb/index.php');
+ $login->setDbh(Toolkit_Database::getInstance());
+ $login->configureForm($auth->config);
+ echo $login->toHtml();
+ }
+
+ // }}}
+
+ // {{{ passwordForm()
+
+ /**
+ * Function to set up the forgot password form
+ *
+ * @return void
+ * @access public
+ */
+ protected function passwordForm()
+ {
+ $pword =& new PasswordForm('member_password');
+ $pword->setDbh(Toolkit_Database::getInstance());
+ $pword->configureForm();
+ echo $pword->toHtml();
+ }
+
+ // }}}
+
+ // {{{ setIdle()
+
+ /**
+ * Set the maximum idle time
+ *
+ * @param integer $time time in seconds
+ * @param boolean $add (optional)add time to current maximum idle time or not
+ *
+ * @return void
+ * @access public
+ */
+ public function setIdle($time = null, $add = false)
+ {
+ $time = is_null($time) ? $this->idleTime : $time;
+ parent::setIdle($time, $add);
+ }
+
+ // }}}
+}
+
+/**
+ * Handles rendering and validating the member login form
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit_FormBuilder
+ */
+class LoginForm extends Toolkit_FormBuilder
+{
+ // {{{ properties
+
+ /**
+ * Custom rules to check for when validating the form
+ *
+ * @var array
+ * @access protected
+ */
+ protected $registeredRules = array();
+
+ /**
+ * Where to perform validation
+ *
+ * @var string
+ * @access protected
+ */
+ protected $validationType = 'client';
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * @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
+ * @param mixed $attributes (optional)Extra attributes for the
tag
+ * @param boolean $trackSubmit (optional)Whether to track if the form
+ * was submitted by adding a special hidden field
+ *
+ * @return void
+ * @access public
+ */
+ public function __construct(
+ $formName,
+ $method = 'post',
+ $action = '',
+ $target = '',
+ $attributes = null,
+ $trackSubmit = false
+ ) {
+ parent::__construct(
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+
+ $this->template = dirname(__FILE__) . '/templates/currentTables/';
+ }
+
+ // }}}
+
+ // {{{ configureElements()
+
+ /**
+ * Sets up the elements to be configured for use with the form
+ *
+ * @param Config_Container $c Configuration object
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureElements(Config_Container $c)
+ {
+ $e = array();
+
+ // get reference to [listing type] section of config file
+ $config =& $c->getItem('section', 'listing type');
+ $singularDirective =& $config->getItem('directive', 'singular');
+ $singularType = $singularDirective->getContent();
+
+ $e[] = array(
+ 'type' => 'header',
+ 'req' => false,
+ 'name' => 'formHdr',
+ 'display' => "$singularType Login"
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'username',
+ 'display' => 'Username'
+ );
+ $e[] = array(
+ 'type' => 'password',
+ 'req' => true,
+ 'name' => 'password',
+ 'display' => 'Password'
+ );
+ $e[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'doLogin',
+ 'display' => 'Login now',
+ 'opts' => array('id' => 'doLogin')
+ );
+ $e[] = array(
+ 'type' => 'link',
+ 'req' => false,
+ 'name' => 'forgot',
+ 'display' => 'Forgot your password? Click',
+ 'opts' => BASE_URL . 'index.php?catid='.MEMBERS_CATEGORY.'&forgot=',
+ 'att' => 'here'
+ );
+
+ $this->setupElements($e);
+ }
+
+ // }}}
+ // {{{ configureFilters()
+
+ /**
+ * Sets up the filters to be used with the form when submitted
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureFilters()
+ {
+ $f = array();
+
+ $f[] = array(
+ 'element' => '__ALL__',
+ 'filter' => 'trim'
+ );
+ $this->setupFilters($f);
+ }
+
+ // }}}
+ // {{{ configureForm()
+
+ /**
+ * Helper method to setup form
+ *
+ * @param Config_Container $c Configuration object
+ *
+ * @return void
+ * @access public
+ */
+ public function configureForm(Config_Container $c)
+ {
+ $this->configureElements($c);
+ $this->configureFilters();
+ $this->configureRules();
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Sets up required rules and extra defined rules for the form
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureRules()
+ {
+ $this->setupRules($r);
+ }
+
+ // }}}
+
+ // {{{ setDbh()
+
+ /**
+ * set the pdo to use for db calls
+ *
+ * @param PDO $pdo PHP Data Object to use
+ *
+ * @return void
+ * @access public
+ */
+ public function setDbh(PDO $pdo)
+ {
+ $this->dbh = $pdo;
+ }
+
+ // }}}
+ // {{{ setupRenderers()
+
+ /**
+ * Inject custom renderers into the forms elements for custom display
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ parent::setupRenderers();
+
+ $renderer =& $this->defaultRenderer();
+ $required = '*';
+ $error = '
{error}
';
+
+ $renderer->setElementTemplate('
{label} {element}
', 'forgot');
+ $renderer->setElementTemplate('
{element}
', 'doLogin');
+ }
+
+ // }}}
+
+ // {{{ toHtml()
+
+ /**
+ * Returns an HTML version of the form
+ *
+ * @return string HTML version of the form
+ * @access public
+ */
+ public function toHtml()
+ {
+ $this->setupRenderers();
+ if ($this->validate()) {
+ header('Location: ' . BASE_URL . 'memberdb/index.php');
+ } elseif ($this->isSubmitted()) {
+ $output = $this->errorMsg;
+ $output .= parent::toHtml();
+ } else {
+ if ($_GET['status']) {
+ switch ($_GET['status']) {
+ case -1 :
+ $error = 'Your session has exceeded the maximum idle time';
+ break;
+
+ case -2 :
+ $error = 'Your session has expired.';
+ break;
+
+ case -3 :
+ $error = 'Invalid username or password.';
+ break;
+
+ case -4 :
+ // This is primarily used for Development.
+ // Users should never be presented with this error.
+ $error = 'Invalid Container';
+ break;
+
+ case -5 :
+ // This is only thrown if the advanced security system
+ // has detected a breach into the system.
+ $error = 'The system has encountered an error. Reference code: -5';
+ break;
+ }
+ $output = "
$error
";
+ }
+ $output .= parent::toHtml();
+ }
+
+ return $output;
+ }
+
+ // }}}
+}
+
+/**
+ * Handles rendering and validating the member password form
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit_FormBuilder
+ */
+class PasswordForm extends Toolkit_FormBuilder
+{
+ // {{{ properties
+
+ /**
+ * Table to query when gathering information
+ *
+ * @var string
+ * @access public
+ */
+ public $tableName = 'member';
+
+ /**
+ * Custom defined rules to validate against when the form is submitted
+ *
+ * @var array
+ * @access protected
+ */
+ protected $registeredRules = array();
+
+ /**
+ * Where to perform validation
+ *
+ * @var string
+ * @access protected
+ */
+ protected $validationType = 'client';
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * @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
+ * @param mixed $attributes (optional)Extra attributes for the
tag
+ * @param boolean $trackSubmit (optional)Whether to track if the form
+ * was submitted by adding a special hidden field
+ *
+ * @return void
+ * @access public
+ */
+ public function __construct(
+ $formName,
+ $method = 'post',
+ $action = '',
+ $target = '',
+ $attributes = null,
+ $trackSubmit = false
+ ) {
+ parent::__construct(
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+
+ $this->template = dirname(__FILE__) . '/templates/currentTables/';
+ }
+
+ // }}}
+
+ // {{{ checkAddressExists()
+
+ /**
+ * Checks to see if the email address exists before allowing an email to go out
+ *
+ * @param string $value submitted email address
+ *
+ * @return boolean If the email address exists or not
+ * @access public
+ */
+ public function checkAddressExists($value)
+ {
+ try {
+ $sql = "
+ SELECT count(*) AS total
+ FROM {$this->tableName}
+ WHERE member_contact_email = :mce";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':mce', $value, PDO::PARAM_STR);
+ $stmt->execute();
+ $stmt->bindColumn('total', $exists);
+ $stmt->fetch();
+
+ return (bool) $exists;
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ configureElements()
+
+ /**
+ * Sets up the elements to be configured for use with the form
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureElements()
+ {
+ $e = array();
+
+ $e[] = array(
+ 'type' => 'header',
+ 'req' => false,
+ 'name' => 'formHdr',
+ 'display' => 'Email Reminder'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'email',
+ 'display' => 'Your Member Contact Email Address'
+ );
+ $e[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'submit',
+ 'display' => 'Send'
+ );
+
+ $this->setupElements($e);
+ }
+
+ // }}}
+ // {{{ configureFilters()
+
+ /**
+ * Sets up the filters to be used with the form when submitted
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureFilters()
+ {
+ $f = array();
+
+ $f[] = array(
+ 'element' => '__ALL__',
+ 'filter' => 'trim'
+ );
+ $this->setupFilters($f);
+ }
+
+ // }}}
+ // {{{ configureForm()
+
+ /**
+ * Helper method to setup form
+ *
+ * @return void
+ * @access public
+ */
+ public function configureForm()
+ {
+ $this->configureElements();
+ $this->configureFilters();
+ $this->configureRules();
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Sets up required rules and extra defined rules for the form
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureRules()
+ {
+ $r = array();
+
+ $r[] = array(
+ 'element' => 'email',
+ 'message' => 'ERROR: Invalid Email Format!',
+ 'type' => 'email',
+ 'format' => null,
+ 'validation' => $this->validationType,
+ 'reset' => true,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => 'email',
+ 'message' => 'ERROR: Cannot locate email address!',
+ 'type' => 'callback',
+ 'format' => array(&$this,
+ 'checkAddressExists'),
+ 'validation' => $this->validationType,
+ 'reset' => true,
+ 'force' => false
+ );
+
+ $this->setupRules($r);
+ }
+
+ // }}}
+
+ // {{{ setDbh()
+
+ /**
+ * set the pdo to use for db calls
+ *
+ * @param PDO $pdo PHP Data Object to use
+ *
+ * @return void
+ * @access public
+ */
+ public function setDbh(PDO $pdo)
+ {
+ $this->dbh = $pdo;
+ }
+
+ // }}}
+ // {{{ setupRenderers()
+
+ /**
+ * Inject custom renderers into the forms elements for custom display
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ parent::setupRenderers();
+
+ $renderer =& $this->defaultRenderer();
+ $required = '*';
+ $error = '
{error}
';
+
+ $renderer->setElementTemplate('
{element}
', 'submit');
+ }
+
+ // }}}
+
+ // {{{ processData()
+
+ /**
+ * Processes the data submitted by the form
+ *
+ * Gets the login credentials for the matching email address and mails
+ * them to that email address
+ *
+ * @param array $values submitted form values
+ *
+ * @return boolean Result of mail
+ * @access protected
+ */
+ protected function processData($values)
+ {
+ try {
+ $sql = "
+ SELECT member_login, member_passwd
+ FROM {$this->tableName}
+ WHERE member_contact_email = :mce";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':mce', $values['email'], PDO::PARAM_STR);
+ $stmt->execute();
+ $row = $stmt->fetch();
+
+ $htmlMsg
+ = "Here is your " . SITENAME . " password:
';
+ }
+ } elseif ($this->isSubmitted()) {
+ $output = $this->errorMsg;
+ $output .= parent::toHtml();
+ } else {
+ $output .= parent::toHtml();
+ }
+
+ return $output;
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/Auxiliary.php b/Toolkit/Members/Auxiliary.php
new file mode 100644
index 0000000..8e7fc50
--- /dev/null
+++ b/Toolkit/Members/Auxiliary.php
@@ -0,0 +1,405 @@
+
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: Auxiliary.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Base class used for building forms to accompany the members database
+ *
+ * This class handles all common functions that are to be used in
+ * the auxiliary forms used to assist in the members DB.
+ * (categories, amenities, regions, etc...).
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: Auxiliary.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://devsys2.gaslightmedia.com/demo.gaslightmedia.com/admin/members/
+ * @see Toolkit_Members, member_admin
+ */
+abstract class Toolkit_Members_Auxiliary
+ extends Toolkit_FormBuilder implements Toolkit_Form
+{
+ // {{{ properties
+
+ /**
+ * Primary table used for database calls
+ *
+ * @var String
+ * @access Public
+ */
+ public $tableName;
+
+ /**
+ * Array of primary table meta data
+ *
+ * This array will hold the column data types for the fields
+ * that will be manipulated in the database.
+ *
+ * @var Array
+ * @access Public
+ */
+ public $tableMetaData;
+
+ /**
+ * The name of the template used for the form
+ *
+ * @var String
+ * @access Protected
+ */
+ protected $formTemplate;
+
+ /**
+ * The object to use inside the form
+ *
+ * This object which is to be populated by the $this object
+ * is used inside the templates and allows access back into the
+ * calling class to call publicly available functions
+ *
+ * @var String
+ * @access Protected
+ */
+ protected $view;
+
+ /**
+ * rules to use with the form
+ * @var array
+ * @access protected
+ */
+ protected $registeredRules = array();
+
+ /**
+ * Setup options to use for rendering the template engine
+ * @var array
+ * @access protected
+ */
+ protected $flexyOptions = array();
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Class constructor
+ *
+ * @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(
+ $formName,
+ $method = 'post',
+ $action = '',
+ $target = '',
+ $attributes = null,
+ $trackSubmit = false
+ ) {
+ parent::__construct(
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+
+ $this->flexyOptions = Toolkit_Members::getFlexyOptions();
+ }
+
+ // }}}
+
+ // {{{ configureDefaults()
+
+ /**
+ * Configure the default values for the form
+ *
+ * Since each form is different, you will need to redefine this
+ * method inside of each subclass and create your own rules
+ * based on your forms elements.
+ *
+ * @return void
+ * @access public
+ */
+ abstract protected function configureDefaults();
+
+ // }}}
+ // {{{ configureFilters()
+
+ /**
+ * Defines all filters used on form elements when submitted
+ *
+ * Most times this function won't need to be overridden.
+ *
+ * @return void
+ * @access public
+ */
+ protected function configureFilters()
+ {
+ $f = array();
+
+ $f[] = array(
+ 'element' => '__ALL__',
+ 'filter' => 'trim'
+ );
+
+ $this->setupFilters($f);
+ }
+
+ // }}}
+
+ // {{{ getSetParameters()
+
+ /**
+ * get a string of sql query parameters
+ *
+ * @param array $values parameters to include
+ *
+ * @return string sql query parameters
+ * @access protected
+ */
+ protected function getSetParameters($values)
+ {
+ $params = array_keys($values);
+ $length = count($params);
+ for ($i = 0; $i < $length; ++$i) {
+ $bindParams .= "{$params[$i]} = :{$params[$i]}";
+ if ($i < ($length - 1)) {
+ $bindParams .= ', ';
+ }
+ }
+ return $bindParams;
+ }
+
+ // }}}
+ // {{{ getDataType()
+
+ /**
+ * Get the data type of the element
+ *
+ * @param string $k element name
+ *
+ * @return element type in the DB
+ * @access protected
+ */
+ protected function getDataType($k)
+ {
+ $metaData = $this->tableMetaData[$k];
+ if ($metaData == 'integer') {
+ return PDO::PARAM_INT;
+ } else if ($metaData == 'boolean') {
+ return PDO::PARAM_BOOL;
+ } elseif ($metaData == 'double precision') {
+ return null;
+ } else {
+ return PDO::PARAM_STR;
+ }
+ }
+
+ // }}}
+
+ // {{{ isEdit()
+
+ /**
+ * Determines if we are editing an object or not
+ *
+ * If we are ever editing an object, member, category, etc...
+ * There will be the objects DB ID passed along in the url under the
+ * id key. If we can find this then we know we're editing, if not
+ * then we are adding.
+ *
+ * @return boolean if the key id is set in the $_GET array
+ * @access public
+ */
+ public function isEdit()
+ {
+ return isset($_GET['id']);
+ }
+
+ // }}}
+
+ // {{{ processData()
+
+ /**
+ * clean unneeded form elements out of the submitted values array
+ *
+ * @param array $values QuickForm submitted elements
+ *
+ * @return boolean Result of insert/update functions
+ * @access public
+ */
+ public function processData($values)
+ {
+ foreach ($values as $k => $v) {
+ switch ($k) {
+ case 'MAX_FILE_SIZE' :
+ unset($values[$k]);
+ break;
+
+ default :
+ if (substr($k, -4) == '_rmv') {
+ unset($values[$k]);
+ }
+ break;
+ }
+ }
+
+ $function = is_numeric($_GET['id']) ? 'updateData' : 'insertData';
+ return $this->$function($values);
+ }
+
+ // }}}
+
+ // {{{ setupElements()
+
+ /**
+ * Add the form elements defined in your class to a QuickForm
+ *
+ * Handles adding singleton elements as well as grouped elements.
+ * If added elements fail to correctly add to the form, the script
+ * should die gracefully, telling the user there was a problem.
+ *
+ * @param array $elements element definitions to setup
+ *
+ * @return void
+ * @throws HTML_QuickForm_Error error raised from QuickForm class.
+ * @access protected
+ */
+ protected function setupElements($elements)
+ {
+ $this->formElements = $elements;
+ foreach ($elements as $e) {
+ if ($e['type'] != 'group') {
+ try {
+ $source =& $this->addElement($e['type'], $e['name'], $e['display'], $e['opts'], $e['att'], $e['val']);
+ } catch (HTML_QuickForm_Error $e) {
+ Toolkit_Common::dieGracefully(null, $e);
+ }
+ if ($e['type'] == 'advmultiselect') {
+ $source->setLabel($e['labels']);
+ }
+ if ($e['name'] == 'categories') {
+ $res = $source->loadArray($this->categories);
+ if (PEAR::isError($res)) {
+ Toolkit_Common::dieGracefully(null, $res);
+ }
+ }
+ if ($e['type'] == 'header') {
+ $this->formHeaders[$e['display']] = $e;
+ }
+ } elseif (is_array($e['group'])) {
+ unset($field);
+ foreach ($e['group'] as $g) {
+ $field[] =& HTML_QuickForm::createElement($g['type'], $g['name'], $g['display'], $g['opts'], $g['att'], $g['val']);
+ }
+ $source =& $this->addGroup($field, $e['name'], $e['label'], $e['seperator'], $e['appendName']);
+ }
+ }
+ }
+
+ // }}}
+ // {{{ setupRenderers()
+
+ /**
+ * Set up the rendering engine templates
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ $renderer =& new HTML_QuickForm_Renderer_Object(true);
+
+ $this->accept($renderer);
+
+ $this->template =& new HTML_Template_Flexy($this->flexyOptions);
+
+ // Make the view a copy of the $this object
+ // That way we have access to call functions in
+ // this class from within the template.
+ $this->view = $this;
+ $this->view->form = $renderer->toObject();
+ $this->template->compile($this->formTemplate);
+ }
+
+ // }}}
+
+ // {{{ toHtml()
+
+ /**
+ * Renders the form for viewing
+ *
+ * This function validates the form if needed, and if it successfully
+ * validates attempts to insert or update the data record.
+ * If it is unsuccessful, it will return an error to the user
+ * informing them of what went wrong.
+ *
+ * @param string $listPage The page the header should redirect
+ * to on successful insert or update.
+ *
+ * @return string The compiled and filled form template.
+ * @access public
+ */
+ public function toHtml($listPage = 'index.php')
+ {
+ // We need to validate (and freeze if needed)
+ // before we render the form. That way the
+ // template knows about any errors on the form.
+ $this->validated = $this->validate();
+ $this->setupRenderers();
+
+ if ($this->validated) {
+ $processed = $this->process(
+ array(&$this, 'processData'),
+ $this->mergeFiles
+ );
+ if ($processed) {
+ header("Location: $listPage");
+ } else {
+ $this->validated = false;
+ $errorMsg = "There was an unexpected error. Please try again later.";
+ }
+ }
+
+ return $errorMsg . $this->template->bufferedOutputObject($this->view);
+ }
+
+ // }}}
+
+ // {{{ validated()
+
+ /**
+ * Returns form message from validation attempts
+ *
+ * @return void
+ * @access public
+ */
+ public function validated()
+ {
+ if ($this->validated) {
+ return $this->successMsg;
+ } elseif ($this->isSubmitted()) {
+ return $this->errorMsg;
+ }
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/CategoryTree.php b/Toolkit/Members/CategoryTree.php
new file mode 100644
index 0000000..4af2366
--- /dev/null
+++ b/Toolkit/Members/CategoryTree.php
@@ -0,0 +1,77 @@
+
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: CategoryTree.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+
+/**
+ * Description for require_once
+ */
+require_once 'Tree.php';
+
+/**
+ * Short description for class
+ *
+ * Long description (if any) ...
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Members_CategoryTree extends Toolkit_Tree
+{
+ // {{{ addChildren()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @return void
+ * @access protected
+ */
+ protected function addChildren()
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM category
+ WHERE parent_id = :parent
+ ORDER BY name";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':parent', $this->catid, PDO::PARAM_INT);
+ $stmt->execute();
+
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $this->children[] = new Toolkit_Members_CategoryTree($row['category_id'],
+ $row['name'],
+ $this->dbh,
+ $row['parent_id']);
+ }
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/City.php b/Toolkit/Members/City.php
new file mode 100644
index 0000000..08ca33c
--- /dev/null
+++ b/Toolkit/Members/City.php
@@ -0,0 +1,412 @@
+
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: City.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Handle City functionality
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: City.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://devsys2.gaslightmedia.com/demo.gaslightmedia.com/admin/members.php?cat=6
+ */
+class Toolkit_Members_City
+{
+ // {{{ properties
+
+ protected $name;
+ protected $region;
+ protected $state;
+ protected $image;
+ protected $description;
+
+ /**
+ * Table name in DB
+ * @var string
+ * @access public
+ */
+ public $tableName = 'city';
+
+ /**
+ * Image Server
+ * @var object
+ * @access protected
+ */
+ protected $is;
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Class constructor
+ *
+ * @param PDO $pdo PHP Data Object
+ *
+ * @access public
+ */
+ public function __construct(PDO $pdo)
+ {
+ $this->dbh = $pdo;
+ }
+
+ // }}}
+
+ // {{{ createNewCity()
+
+ /**
+ * Creates a new city in the DB
+ *
+ * @return void
+ * @access public
+ */
+ public function createNewCity()
+ {
+ // Minimum required fields to have an array
+ if (!is_numeric($this->state) || empty($this->name)) {
+ return false;
+ }
+
+ if ($this->_isDuplicate()) {
+ return PEAR::raiseError('This city already exists');
+ }
+
+ $values = array(
+ 'city_name' => $this->name,
+ 'state_id' => $this->state,
+ 'region_id' => $this->region,
+ 'description' => $this->description,
+ 'image' => $this->image,
+ );
+
+ $sql = Toolkit_Common::createSQLInsert(
+ $this->tableName,
+ array_keys($values)
+ );
+
+ try {
+ return Toolkit_Common::processQuery($this->dbh, $sql, $values);
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ deleteCity()
+
+ /**
+ * delete a city from the DB
+ *
+ * @param integer $id city record to delete
+ *
+ * @return void
+ * @access public
+ */
+ public function deleteCity($id)
+ {
+ if (!is_numeric($id)) {
+ return false;
+ }
+
+ $sql = "
+ DELETE FROM {$this->tableName}
+ WHERE city_id = :id";
+
+ try {
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $id, PDO::PARAM_INT);
+ return $stmt->execute();
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ getName()
+
+ /**
+ * get the name of the city
+ *
+ * @return void
+ * @access public
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ // }}}
+ // {{{ getState()
+
+ /**
+ * get the state the city belongs in
+ *
+ * @return void
+ * @access public
+ */
+ public function getState()
+ {
+ return $this->state;
+ }
+
+ // }}}
+ // {{{ getRegion()
+
+ /**
+ * get the Region the city belongs in
+ *
+ * @return void
+ * @access public
+ */
+ public function getRegion()
+ {
+ return $this->region;
+ }
+
+ // }}}
+ // {{{ getImage()
+
+ /**
+ * get the city image
+ *
+ * @param string $uri URI location to find the image at
+ *
+ * @return string file name of image, or html img tag of image
+ * @access public
+ */
+ public function getImage($uri = null)
+ {
+ if (is_null($uri)) {
+ return $this->image;
+ } else {
+ $path = $uri . $this->image;
+ $imageSize = $this->is->getImageSize($path);
+ $img = "";
+ return $img;
+ }
+ }
+
+ // }}}
+ // {{{ getDesc()
+
+ /**
+ * get the description of the city
+ *
+ * @return string city description
+ * @access public
+ */
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ // }}}
+
+ // {{{ _isDuplicate()
+
+ /**
+ * get the description of the city
+ *
+ * @param integer $ignore city records to not include in count
+ *
+ * @return string city description
+ * @access private
+ */
+ private function _isDuplicate($ignore = null)
+ {
+ $sql = "
+ SELECT count(*) AS total
+ FROM {$this->tableName}
+ WHERE city_name = :name
+ AND state_id = :state";
+
+ if (is_numeric($ignore)) {
+ $sql .= " AND city_id != $ignore";
+ }
+
+ try {
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':name', $this->name, PDO::PARAM_STR);
+ $stmt->bindParam(':state', $this->state, PDO::PARAM_INT);
+ $stmt->execute();
+ $stmt->bindColumn('total', $total);
+ $stmt->fetch();
+
+ return (bool) $total;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ setName()
+
+ /**
+ * set the name of the city
+ *
+ * @param string $name City Name
+ *
+ * @return void
+ * @access public
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ // }}}
+ // {{{ setState()
+
+ /**
+ * set the state the city belongs in
+ *
+ * @param integer $state state id from db
+ *
+ * @return void
+ * @access public
+ * @throws PEAR_Error
+ */
+ public function setState($state)
+ {
+ if (!is_numeric($state)) {
+ return PEAR::raiseError('Invalid state id');
+ }
+
+ $this->state = $state;
+ }
+
+ // }}}
+ // {{{ setRegion()
+
+ /**
+ * set the Region the city belongs in
+ *
+ * @param integer $region region id from db
+ *
+ * @return void
+ * @access public
+ * @throws PEAR_Error
+ */
+ public function setRegion($region)
+ {
+ if (!is_numeric($region)) {
+ return PEAR::raiseError('Invalid region id');
+ }
+ $this->region = $region;
+ }
+
+ // }}}
+ // {{{ setImage()
+
+ /**
+ * set the city image
+ *
+ * @param string $image the city image
+ *
+ * @return void
+ * @access public
+ */
+ public function setImage($image)
+ {
+ $this->image = $image;
+ }
+
+ // }}}
+ // {{{ setImageServer()
+
+ /**
+ * set the image server to use
+ *
+ * @param Toolkit_Image_Server $is Image Server Instance
+ *
+ * @return void
+ * @access public
+ */
+ public function setImageServer(Toolkit_Image_Server $is)
+ {
+ $this->is = $is;
+ }
+
+ // }}}
+ // {{{ setDesc()
+
+ /**
+ * set the description of the city
+ *
+ * @param string $desc City Description
+ *
+ * @return void
+ * @access public
+ */
+ public function setDescription($desc)
+ {
+ $this->description = $desc;
+ }
+
+ // }}}
+
+ // {{{ updateCity()
+
+ /**
+ * update a city in the DB
+ *
+ * @param integer $id record id to update
+ *
+ * @return void
+ * @access public
+ */
+ public function updateCity($id)
+ {
+ // Minimum required fields to have an array
+ if (!is_numeric($this->state) || empty($this->name)) {
+ return false;
+ }
+
+ if ($this->_isDuplicate($id)) {
+ return PEAR::raiseError('This city already exists');
+ }
+
+ $values = array(
+ 'city_name' => $this->name,
+ 'state_id' => $this->state,
+ 'region_id' => $this->region,
+ 'description' => $this->description,
+ 'image' => $this->image,
+ );
+
+ $sql = Toolkit_Common::createSQLUpdate(
+ $this->tableName,
+ array_keys($values),
+ array('city_id = :city_id')
+ );
+
+ $values['city_id'] = $id;
+
+ try {
+ return Toolkit_Common::processQuery($this->dbh, $sql, $values);
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/Display.php b/Toolkit/Members/Display.php
new file mode 100644
index 0000000..1428160
--- /dev/null
+++ b/Toolkit/Members/Display.php
@@ -0,0 +1,187 @@
+
+ * @copyright 2008 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: Display.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+require_once 'HTML/Select.php';
+require_once 'HTML/Template/Flexy.php';
+require_once 'Members/SearchList.php';
+require_once 'Members/UserSearchForm.php';
+
+/**
+ * Handles Displaying member lists and profile pages
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2008 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Members_Display
+{
+ // {{{ properties
+
+ /**
+ * The Database Handler
+ *
+ * @var object
+ * @access protected
+ */
+ public $dbh;
+
+ /**
+ * Search radius distance
+ * @var integer
+ * @access protected
+ */
+ protected $radius = 35;
+
+ /**
+ * Page catid
+ *
+ * @var integer
+ * @access private
+ */
+ private $_catid;
+
+ /**
+ * Number of records to show per page
+ *
+ * Set to NULL to show all records on one page.
+ *
+ * @var integer
+ * @access protected
+ */
+ protected $limit = 10;
+
+ /**
+ * The list of members
+ *
+ * @var string
+ * @access protected
+ */
+ protected $membersList;
+
+ /**
+ * Whether to randomize the list of members or not
+ *
+ * @var bool
+ * @access protected
+ */
+ protected $randomize = false;
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * @param PDO $pdo PHP Data Object to use for DB calls
+ *
+ * @return void
+ * @access public
+ */
+ public function __construct(PDO $pdo)
+ {
+ $this->dbh = $pdo;
+ }
+
+ // }}}
+
+ // {{{ hideUserSearchForm()
+
+ /**
+ * Get the status of displaying the search form for a page
+ *
+ * @return bool true if yes, false otherwise.
+ * @access public
+ */
+ public function hideUserSearchForm()
+ {
+ try {
+ $sql = "
+ SELECT CASE
+ WHEN no_search_form THEN 1 ELSE 0
+ END as no_search_form
+ FROM bus_category
+ WHERE id = :catid";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':catid', $this->_catid, PDO::PARAM_INT);
+ $stmt->execute();
+ $row = $stmt->fetch();
+ return $row['no_search_form'];
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ setCatId()
+
+ /**
+ * Set the catid for the page
+ *
+ * @param integer $catid page id from db
+ *
+ * @return void
+ * @access public
+ * @throws PEAR Error on invalid member id
+ */
+ public function setCatId($catid)
+ {
+ if (is_numeric($catid) && ctype_digit((string) $catid)) {
+ $this->_catid = $catid;
+ } else {
+ $this->_catid = null;
+ throw new PEAR_Exception('Invalid catid');
+ }
+ }
+
+ // }}}
+ // {{{ setMemberSections()
+
+ /**
+ * Sets an array with all the member category types assigned to a page
+ *
+ * Collects all member categories assigned to a page from the
+ * admin Toolbox.
+ *
+ * @return void
+ * @access public
+ */
+ public function setMemberSections()
+ {
+ try {
+ $sql = "
+ SELECT count(*) AS total, bc.category
+ FROM bus_cat_member bcm, bus_category bc
+ WHERE bcm.catid = :catid
+ AND bcm.catid = bc.id
+ GROUP BY bc.category";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':catid', $this->_catid, PDO::PARAM_INT);
+ $stmt->execute();
+ $row = $stmt->fetch();
+ if ($row['total']) {
+ $this->memberSections[$this->_catid] = $row['category'];
+ }
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/EditMemberAmenities.php b/Toolkit/Members/EditMemberAmenities.php
new file mode 100644
index 0000000..e2ca8ea
--- /dev/null
+++ b/Toolkit/Members/EditMemberAmenities.php
@@ -0,0 +1,301 @@
+
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: EditMemberAmenities.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Short description for class
+ *
+ * Long description (if any) ...
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Members_EditMemberAmenities
+ extends Toolkit_Members_EditMemberInfo implements Toolkit_Form
+{
+ // {{{ properties
+
+ /**
+ * The Table name used to store the data of the member record in the database.
+ *
+ * @var string
+ * @access public
+ */
+ public $tableName = 'member_amenity';
+
+ /**
+ * The name of the template used to render the business info form.
+ *
+ * @var string
+ * @access protected
+ */
+ protected $formTemplate = 'editAmenities.tpl';
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Class constructor
+ *
+ * @param PDO $pdo PHP Data Object to use for DB calls
+ * @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
+ * @see Toolkit_Members_EditMemberInfo
+ */
+ public function __construct(
+ PDO $pdo,
+ $formName,
+ $method = 'post',
+ $action = '',
+ $target = '',
+ $attributes = null,
+ $trackSubmit = false
+ ) {
+ parent::__construct(
+ $pdo,
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+ }
+
+ // }}}
+
+ // {{{ configureDefaults()
+
+ /**
+ * Sets the defaults for elements in the form.
+ *
+ * @return array form element default values
+ * @access public
+ */
+ public function configureDefaults()
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE member_id = :id ";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->execute();
+
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $defaults[$row['amenity_id']] = true;
+ }
+ $this->setupDefaults($defaults);
+ return $defaults;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ configureElements()
+
+ /**
+ * Setup the element definitions to use on the form.
+ *
+ * @return void
+ * @access public
+ */
+ public function configureElements()
+ {
+ // Element definitions
+ $e = array();
+ $amenities = $this->getAmenities();
+ $half = floor(count($amenities) / 2);
+ $i = 0;
+ // All Grouped Elements are created here.
+
+ // All Elements are created here. This includes group element definitions.
+ $e[] = array(
+ 'type' => 'header',
+ 'req' => false,
+ 'name' => 'row1'
+ );
+ while ($i < $half) {
+ $e[] = array(
+ 'type' => 'checkbox',
+ 'req' => false,
+ 'name' => $amenities[$i]['amenity_id'],
+ 'display' => $amenities[$i++]['amenity_name']
+ );
+ }
+ $e[] = array(
+ 'type' => 'header',
+ 'req' => false,
+ 'name' => 'row2'
+ );
+ while ($i < count($amenities)) {
+ $e[] = array(
+ 'type' => 'checkbox',
+ 'req' => false,
+ 'name' => $amenities[$i]['amenity_id'],
+ 'display' => $amenities[$i++]['amenity_name']
+ );
+ }
+
+ $this->setupElements($e);
+ }
+
+ // }}}
+ // {{{ configureForm()
+
+ /**
+ * Wrapper function to handle setting up the form
+ *
+ * @return void
+ * @access public
+ */
+ public function configureForm()
+ {
+ $this->configureElements();
+ $this->configureRules();
+ $this->configureDefaults();
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Sets up all the rules to be used when the form is validated.
+ *
+ * @return void
+ * @access public
+ */
+ public function configureRules()
+ {
+ $this->setupRules();
+ }
+
+ // }}}
+
+ // {{{ getAmenities()
+
+ /**
+ * Gets all the amentities
+ *
+ * @return $a array The array of amenities from the DB.
+ * @access protected
+ */
+ protected function getAmenities()
+ {
+ $a = array();
+ try {
+ $sql = "
+ SELECT *
+ FROM amenity
+ ORDER BY amenity_name";
+ foreach ($this->dbh->query($sql) as $row) {
+ $a[] = $row;
+ }
+ } catch (PDOException $e) {
+ $this->handleError($e);
+ }
+ return $a;
+ }
+
+ // }}}
+
+ // {{{ insertData()
+
+ /**
+ * Create a new record in the database from the data on the form
+ *
+ * @param array $values Form values
+ *
+ * @return boolean False on error, True otherwise.
+ * @access public
+ */
+ public function insertData($values)
+ {
+ try {
+ $sql = "
+ DELETE FROM {$this->tableName}
+ WHERE member_id = :id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->execute();
+
+ $params = implode(', ', array_keys($values));
+ $bindParams = ':' . implode(', :', array_keys($values));
+ $sql = "
+ INSERT INTO {$this->tableName} (member_id, amenity_id)
+ VALUES (:member_id, :aid)";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $_GET['id'], PDO::PARAM_INT);
+ foreach ($values as $k => $v) {
+ $stmt->bindParam(':aid', $k, PDO::PARAM_INT);
+ $stmt->execute();
+ }
+
+ $cache = new Cache_Lite(Toolkit_Members::getCacheOptions());
+ $cache->remove("Member_Profile-{$_GET['id']}", 'Dynamic');
+
+ return true;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ processData()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param array $values Parameter description (if any) ...
+ *
+ * @return array Return description (if any) ...
+ * @access public
+ */
+ public function processData($values)
+ {
+ Toolkit_Common::getTableMetaData();
+
+ foreach ($values as $k => $v) {
+ switch ($k) {
+ default :
+ if (preg_match('/^.+_rmv$/', $k)) {
+ unset($values[$k]);
+ }
+ break;
+ }
+ }
+
+ return $this->insertData($values);
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/EditMemberContacts.php b/Toolkit/Members/EditMemberContacts.php
new file mode 100644
index 0000000..225e798
--- /dev/null
+++ b/Toolkit/Members/EditMemberContacts.php
@@ -0,0 +1,728 @@
+
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: EditMemberContacts.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Handle associating contacts along with member records
+ *
+ * Controls all aspects of creating and rendering the form used to manipulate
+ * the business contacts. Form is not rendered until the user is added into
+ * the Database.
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit_Members
+ */
+class Toolkit_Members_EditMemberContacts
+ extends Toolkit_Members_EditMemberInfo implements Toolkit_Form
+{
+ // {{{ properties
+
+ /**
+ * The table name in the database used to store the data of the files
+ *
+ * @var string
+ * @access public
+ */
+ public $tableName = 'member_contacts';
+
+ /**
+ * The template used to render the form
+ *
+ * @var string
+ * @access protected
+ */
+ protected $formTemplate = 'editContacts.tpl';
+
+ /**
+ * Message to return if the form successfully submits
+ *
+ * @var string
+ * @access protected
+ */
+ protected $successMsg = '
+
+ You successfully updated your contact.
+
';
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Class constructor
+ *
+ * @param PDO $pdo PHP Data Object to use for DB calls
+ * @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
+ * @see Toolkit_Members_EditMemberInfo
+ */
+ public function __construct(
+ PDO $pdo,
+ $formName,
+ $method = 'post',
+ $action = '',
+ $target = '',
+ $attributes = null,
+ $trackSubmit = false
+ ) {
+ parent::__construct(
+ $pdo,
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+ }
+
+ // }}}
+
+ // {{{ configureDefaults()
+
+ /**
+ * Sets the defaults for elements in the form.
+ *
+ * @return void
+ * @access public
+ */
+ public function configureDefaults()
+ {
+ try {
+ if (isset($_GET['cid'])) {
+ $sql = "
+ select * from {$this->tableName} where id = :cid";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':cid', $_GET['cid'], PDO::PARAM_INT);
+ $stmt->execute();
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+ $defaults['id'] = $row['id'];
+ $defaults['title'] = $row['title'];
+ $defaults['fname'] = $row['fname'];
+ $defaults['lname'] = $row['lname'];
+ $defaults['email'] = $row['email'];
+ $defaults['phone'] = $row['phone'];
+ $defaults['send_mail'] = $row['send_mail'];
+ }
+ $sql = "
+ SELECT *, fname || ' ' || lname AS name,
+ CASE send_mail
+ WHEN 'true' THEN 'Can Mail'
+ ELSE 'No Mail'
+ END AS send_mail
+ FROM {$this->tableName}
+ WHERE member_id = :id
+ ORDER BY id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->execute();
+
+ $i = 0;
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $defaults["cid$i"] = $row['id'];
+ $defaults["title$i"] = $row['title'];
+ $defaults["name$i"] = $row['name'];
+ $defaults["email$i"] = $row['email'];
+ $defaults["phone$i"] = $row['phone'];
+ $defaults["send_mail$i"] = $row['send_mail'];
+ ++$i;
+ }
+ $this->setupDefaults($defaults);
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ configureElements()
+
+ /**
+ * Setup the elements to use on the form.
+ *
+ * @return void
+ * @access public
+ */
+ public function configureElements()
+ {
+ $e = array();
+ $contacts = $this->getMemberContacts();
+ // All Grouped Elements are created here.
+ $submitText = (isset($_GET['cid'])) ? 'Update' : 'Submit';
+
+ // All Elements are created here. This includes group element definitions.
+ $e[] = array(
+ 'type' => 'header',
+ 'req' => false,
+ 'name' => 'fileHdr',
+ 'display' => 'Contacts'
+ );
+ $e[] = array(
+ 'type' => 'hidden',
+ 'req' => false,
+ 'name' => 'id'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'title',
+ 'display' => 'Title',
+ 'opts' => array('class' => 'text')
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'fname',
+ 'display' => 'First Name',
+ 'opts' => array('class' => 'text')
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'lname',
+ 'display' => 'Last Name',
+ 'opts' => array('class' => 'text')
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'email',
+ 'display' => 'Email',
+ 'opts' => array('class' => 'text')
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'phone',
+ 'display' => 'Phone',
+ 'opts' => array('class' => 'text')
+ );
+ $e[] = array(
+ 'type' => 'advcheckbox',
+ 'req' => false,
+ 'name' => 'send_mail',
+ 'display' => 'Receive Mail',
+ 'val' => array(0, 1)
+ );
+ $e[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'submit',
+ 'display' => $submitText,
+ 'opts' => array('class' => 'submit')
+ );
+ if (is_array($contacts)) {
+ foreach ($contacts as $k => $v) {
+ $e[] = array(
+ 'type' => 'header',
+ 'req' => false,
+ 'name' => "fileHdr$k"
+ );
+ $e[] = array(
+ 'type' => 'static',
+ 'req' => false,
+ 'name' => "cid$k"
+ );
+ $e[] = array(
+ 'type' => 'static',
+ 'req' => false,
+ 'name' => "name$k",
+ 'display' => 'Name'
+ );
+ $e[] = array(
+ 'type' => 'static',
+ 'req' => false,
+ 'name' => "title$k"
+ );
+ $e[] = array(
+ 'type' => 'static',
+ 'req' => false,
+ 'name' => "email$k",
+ 'display' => 'Email'
+ );
+ $e[] = array(
+ 'type' => 'static',
+ 'req' => false,
+ 'name' => "phone$k",
+ 'display' => 'Phone'
+ );
+ $e[] = array(
+ 'type' => 'static',
+ 'req' => false,
+ 'name' => "send_mail$k",
+ 'display' => 'Receive Mail'
+ );
+ }
+ }
+
+ $this->setupElements($e);
+ }
+
+ // }}}
+ // {{{ configureForm()
+
+ /**
+ * Wrapper function to handle setting up the form
+ *
+ * @return void
+ * @access public
+ */
+ public function configureForm()
+ {
+ $this->configureElements();
+ $this->configureRules();
+ $this->configureDefaults();
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Sets up all the rules to be used when the form is validated.
+ *
+ * @return void
+ * @access public
+ */
+ public function configureRules()
+ {
+ // form rules
+ $r = array();
+ $this->registeredRules = array('phone', 'email');
+ $r[] = array(
+ 'element' => 'email',
+ 'message' => 'ERROR: Invalid Email Address!',
+ 'type' => 'email',
+ 'format' => null,
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ /*
+ $r[] = array(
+ 'element' => 'phone',
+ 'message' => 'ERROR: Invalid Phone Number!',
+ 'type' => 'phone',
+ 'format' => null,
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ */
+ $this->setupRules($r);
+ }
+
+ // }}}
+
+ // {{{ getDelUrl()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param object $sec Parameter description (if any) ...
+ *
+ * @return mixed Return description (if any) ...
+ * @access public
+ */
+ public function getDelUrl($sec)
+ {
+ return $_SERVER['REQUEST_URI'] . "&d=t&cid={$sec->elements[0]->html}";
+ }
+
+ // }}}
+ // {{{ getEditUrl()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param object $sec Parameter description (if any) ...
+ *
+ * @return mixed Return description (if any) ...
+ * @access public
+ */
+ public function getEditUrl($sec)
+ {
+ return $_SERVER['REQUEST_URI'] . "&cid={$sec->elements[0]->html}";
+ }
+
+ // }}}
+ // {{{ getImgUrl()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param unknown $type Parameter description (if any) ...
+ *
+ * @return string Return description (if any) ...
+ * @access public
+ */
+ public function getImgUrl($type)
+ {
+ return BASE_URL . "assets/$type";
+ }
+
+ // }}}
+ // {{{ getMailIcon()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param object $sec Parameter description (if any) ...
+ *
+ * @return string Return description (if any) ...
+ * @access public
+ */
+ public function getMailIcon($sec)
+ {
+ $status = $sec->elements[5]->html;
+ $icon = ($status == 'No Mail') ? '-Not-Ok' : '-Ok';
+ return '';
+ }
+
+ // }}}
+ // {{{ getMemberContacts()
+
+ /**
+ * Get all the contacts data uploaded to a member into an array
+ *
+ * @return array member contacts
+ * @access protected
+ */
+ protected function getMemberContacts()
+ {
+ $c = array();
+ try {
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE member_id = :id
+ ORDER BY id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->execute();
+
+ while ($row = $stmt->fetch()) {
+ $c[] = $row;
+ }
+ return $c;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ insertData()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param array $values Parameter description (if any) ...
+ *
+ * @return object Return description (if any) ...
+ * @access public
+ */
+ public function insertData($values)
+ {
+ unset(
+ $values['id'],
+ $values['target'],
+ $values['submit']
+ );
+ $values['member_id'] = $_GET['id'];
+ try {
+ $params = implode(', ', array_keys($values));
+ $bindParams = ':' . implode(', :', array_keys($values));
+ $sql = "
+ INSERT INTO {$this->tableName} ($params)
+ VALUES ($bindParams)";
+ $stmt = $this->dbh->prepare($sql);
+ foreach ($values as $k => $v) {
+ $metaData = $this->tableMetaData[$k];
+ if ($metaData == 'integer') {
+ $dataType = PDO::PARAM_INT;
+ } else if ($metaData == 'boolean') {
+ $dataType = PDO::PARAM_BOOL;
+ } elseif ($metaData == 'double precision') {
+ $dataType = null;
+ } else {
+ $dataType = PDO::PARAM_STR;
+ }
+ $stmt->bindParam(":$k", $values[$k], $dataType);
+ }
+ return $stmt->execute();
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ isForm()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param unknown $sec Parameter description (if any) ...
+ *
+ * @return unknown Return description (if any) ...
+ * @access public
+ */
+ public function isForm($sec)
+ {
+ return !$sec;
+ }
+
+ // }}}
+ // {{{ isName()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param unknown $name Parameter description (if any) ...
+ *
+ * @return mixed Return description (if any) ...
+ * @access public
+ */
+ public function isName($name)
+ {
+ return (substr($name, 0, 4) == 'name') ? true : false;
+ }
+
+ // }}}
+ // {{{ isPhone()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param unknown $name Parameter description (if any) ...
+ *
+ * @return mixed Return description (if any) ...
+ * @access public
+ */
+ public function isPhone($name)
+ {
+ return (substr($name, 0, 5) == 'phone') ? true : false;
+ }
+
+ // }}}
+ // {{{ isEmail()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param unknown $name Parameter description (if any) ...
+ *
+ * @return mixed Return description (if any) ...
+ * @access public
+ */
+ public function isEmail($name)
+ {
+ return (substr($name, 0, 5) == 'email') ? true : false;
+ }
+
+ // }}}
+ // {{{ isTitle()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param unknown $name Parameter description (if any) ...
+ *
+ * @return mixed Return description (if any) ...
+ * @access public
+ */
+ public function isTitle($name)
+ {
+ return (substr($name, 0, 5) == 'title') ? true : false;
+ }
+
+ // }}}
+
+ // {{{ processData()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param array $values Parameter description (if any) ...
+ *
+ * @return void
+ * @access public
+ */
+ public function processData($values)
+ {
+ Toolkit_Common::getTableMetaData();
+ if (empty($values['id'])) {
+ $this->insertData($values);
+ } else {
+ $this->updateData($values);
+ }
+ $listPage = BASE_URL .
+ "admin/members.php?cat=2&subCat=2&tab=6&id={$_GET['id']}";
+ header("Location: $listPage");
+ }
+
+ // }}}
+
+ // {{{ removeContact()
+
+ /**
+ * Remove a contact from a member record
+ *
+ * @param integer $cid contact id
+ * @param integer $mid member id
+ *
+ * @return void
+ * @access public
+ */
+ public function removeContact($cid, $mid)
+ {
+ try {
+ $sql = "
+ DELETE FROM {$this->tableName}
+ WHERE id = :cid
+ AND member_id = :mid";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':cid', $cid, PDO::PARAM_INT);
+ $stmt->bindParam(':mid', $mid, PDO::PARAM_INT);
+ $stmt->execute();
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ show()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @return void
+ * @access public
+ */
+ public function show()
+ {
+ if (isset($_GET['d'])) {
+ $this->removeContact($_GET['cid']);
+ $target = BASE_URL . 'admin/members.php?cat=2&subCat=2&tab=6&id=';
+ $target .= $_GET['id'];
+ header("Location: $target");
+ }
+ Toolkit_Common::show();
+ }
+
+ // }}}
+
+ // {{{ updateData()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param array $values Parameter description (if any) ...
+ *
+ * @return boolean Return description (if any) ...
+ * @access public
+ */
+ public function updateData($values)
+ {
+ if (array_key_exists('delete', $values)) {
+ $this->deleteFile($values);
+ }
+
+ unset(
+ $values['target'],
+ $values['submit']
+ );
+
+ try {
+ $params = array_keys($values);
+ $length = count($params);
+ for ($i = 0; $i < $length; ++$i) {
+ $bindParams .= "{$params[$i]} = :{$params[$i]}";
+ if ($i < ($length - 1)) {
+ $bindParams .= ', ';
+ }
+ }
+ $sql = "
+ UPDATE {$this->tableName}
+ SET $bindParams
+ WHERE id = :id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $pid, PDO::PARAM_INT);
+ foreach ($values as $k => $v) {
+ $metaData = $this->tableMetaData[$k];
+ if ($metaData == 'integer') {
+ $dataType = PDO::PARAM_INT;
+ } else if ($metaData == 'boolean') {
+ $dataType = PDO::PARAM_BOOL;
+ } else {
+ $dataType = PDO::PARAM_STR;
+ }
+ $stmt->bindParam(":$k", $values[$k], $dataType);
+ }
+ $stmt->execute();
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ return false;
+ }
+ return true;
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/EditMemberFile.php b/Toolkit/Members/EditMemberFile.php
new file mode 100644
index 0000000..24e10a0
--- /dev/null
+++ b/Toolkit/Members/EditMemberFile.php
@@ -0,0 +1,549 @@
+
+ * @author Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: EditMemberFile.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Controls for uploading / editing files for a business record
+ *
+ * Controls all aspects of creating and rendering the form used to manipulate
+ * the business files. Form is not rendered until the user is added into the Database.
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Steve Sutton
+ * @author Jamie Kahgee
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Members_EditMemberFile
+ extends Toolkit_Members_EditMemberInfo implements Toolkit_Form
+{
+ // {{{ properties
+
+ /**
+ * The table name in the database used to store the data of the files
+ *
+ * @var string
+ * @access public
+ */
+ public $tableName = 'member_files';
+
+ /**
+ * The template used to render the form
+ *
+ * @var string
+ * @access protected
+ */
+ protected $formTemplate = 'editFile.tpl';
+
+ /**
+ * Where the uploaded files are stored.
+ *
+ * @var string
+ * @access protected
+ */
+ protected $uploadDir = 'uploads/member_files/';
+
+ /**
+ * Message to return if the form successfully submits
+ *
+ * @var string
+ * @access protected
+ */
+ protected $successMsg = '
+
+ You successfully updated your file.
+
';
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Class constructor
+ *
+ * @param PDO $pdo PHP Data Object to use for DB calls
+ * @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
+ * @see Toolkit_Members_EditMemberInfo
+ */
+ public function __construct(
+ PDO $pdo,
+ $formName,
+ $method = 'post',
+ $action = '',
+ $target = '',
+ $attributes = null,
+ $trackSubmit = false
+ ) {
+ parent::__construct(
+ $pdo,
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+
+ // Make sure we have the upload directory actually created so we can store our uploaded files.
+ if (!is_dir(BASE . $this->uploadDir)) {
+ $oldUmask = umask(0);
+ mkdir(BASE . $this->uploadDir, 0770);
+ umask($oldUmask);
+ }
+ }
+
+ // }}}
+
+ // {{{ configureDefaults()
+
+ /**
+ * Sets the defaults for elements in the form.
+ *
+ * @return void
+ * @access public
+ */
+ public function configureDefaults()
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE member_id = :id
+ ORDER BY id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->execute();
+
+ $i = 0;
+ $imgTag = ' ';
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $defaults["file$i"] = $row['id'];
+ $defaults["file_name$i"] = (empty($row['file_name'])) ?
+ $row['original_name'] : $row['file_name'];
+
+ $oname = (empty($row['file_name'])) ?
+ $row['original_name'] : $row['file_name'];
+ $defaults["original_name$i"] = '
' .
+ $imgTag . $oname . '
';
+ ++$i;
+ }
+ $this->setupDefaults($defaults);
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ configureElements()
+
+ /**
+ * Setup the elements to use on the form.
+ *
+ * @return void
+ * @access public
+ */
+ public function configureElements()
+ {
+ $files = $this->getMemberFiles();
+ // All Grouped Elements are created here.
+
+ // All Elements are created here. This includes group element definitions.
+ $elements[] = array('type' => 'header', 'req' => false, 'name' => 'fileHdr', 'display' => 'Files');
+ if (isset($_POST['uploaded_file_rmv'])) {
+ $elements[] = array('type' => 'hidden', 'req' => false, 'name' => 'uploaded_file_rmv');
+ }
+ $elements[] = array('type' => 'text', 'req' => false, 'name' => 'file_name', 'display' => 'File Name');
+ $elements[] = array('type' => 'file', 'req' => false, 'name' => 'file_rmv', 'display' => 'Upload a File', 'opts' => array('class' => 'submit'));
+ $elements[] = array('type' => 'submit', 'req' => false, 'name' => 'submitNewFile', 'display' => 'Upload new file', 'opts' => array('class' => 'submit'));
+
+ if (is_array($files)) {
+ foreach ($files as $k => $v) {
+ $elements[] = array('type' => 'header', 'req' => false, 'name' => "fileHdr$k");
+ $elements[] = array('type' => 'hidden', 'req' => false, 'name' => "file$k");
+ $elements[] = array('type' => 'static', 'req' => false, 'name' => "original_name$k");
+ $elements[] = array('type' => 'text', 'req' => false, 'name' => "file_name$k", 'display' => 'File Name', 'opts' => array('class' => 'text'));
+ $elements[] = array('type' => 'submit', 'req' => false, 'name' => 'update', 'display' => 'Update File Name', 'opts' => array('class' => 'submit'));
+ $elements[] = array('type' => 'submit', 'req' => false, 'name' => 'delete', 'display' => 'Delete File', 'opts' => array('class' => 'photoDelete fileDelete'));
+ }
+ }
+
+ $this->setupElements($elements);
+ }
+
+ // }}}
+ // {{{ configureForm()
+
+ /**
+ * Wrapper function to handle setting up the form
+ *
+ * @return void
+ * @access public
+ */
+ public function configureForm()
+ {
+ $this->configureElements();
+ $this->configureRules();
+ $this->configureDefaults();
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Sets up all the rules to be used when the form is validated.
+ *
+ * @return void
+ * @access public
+ */
+ public function configureRules()
+ {
+ $this->registeredRules = array('memberfile');
+ $mimeTypes = array(
+ 'application/pdf',
+ 'application/msword',
+ );
+
+ $r = array();
+
+ if (!empty($_FILES['file_rmv']['tmp_name'])) {
+ $r[] = array(
+ 'element' => 'file_rmv',
+ 'message' => 'ERROR: Incorrect File Type (.pdf, .doc) only!',
+ 'type' => 'mimetype',
+ 'format' => $mimeTypes,
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ }
+ $r[] = array(
+ 'element' => 'file_rmv',
+ 'message' => 'ERROR: Invalid File!',
+ 'type' => 'memberfile',
+ 'format' => array($this, false),
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ $this->setupRules($r);
+ }
+
+ // }}}
+
+ // {{{ deleteFile()
+
+ /**
+ * Remove the file from the disk and delet from the database
+ *
+ * @param string $values Form values
+ *
+ * @return boolean
+ * @access protected
+ */
+ protected function deleteFile($values)
+ {
+ try {
+ $fid = $values["file{$values['target']}"];
+ $this->dbh->beginTransaction();
+ // Get the file name so we know what to look for when we try to
+ // delete the file from the disk.
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE id = :id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $fid, PDO::PARAM_INT);
+ $stmt->execute();
+ $file = $stmt->fetch(PDO::FETCH_ASSOC);
+ // Make sure the file actually exists, then try to remove it.
+ if (file_exists(BASE . $this->uploadDir . $file['name_on_disk'])) {
+ unlink(BASE . $this->uploadDir . $file['name_on_disk']);
+ }
+
+ // Remove the photo from the updates table if one is present.
+ $sql = "
+ DELETE FROM {$this->pendingTable}
+ WHERE db_table = '{$this->tableName}'
+ AND member_id = :member_id
+ AND foreign_key = :id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->bindParam(':id', $fid, PDO::PARAM_INT);
+ $stmt->execute();
+
+ // Remove the file from the member.
+ $sql = "
+ DELETE FROM {$this->tableName}
+ WHERE id = :id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $fid, PDO::PARAM_INT);
+ $stmt->execute();
+ return $this->dbh->commit();
+ } catch (PDOException $e) {
+ $this->dbh->rollBack();
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ findTargetFile()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param array $values Parameter description (if any) ...
+ *
+ * @return integer Return description (if any) ...
+ * @access protected
+ */
+ protected function findTargetFile($values)
+ {
+ foreach ($values as $k => $v) {
+ if (preg_match('/^file_name.+$/', $k, $matches)) {
+ return substr($k, 9);
+ }
+ }
+ }
+
+ // }}}
+
+ // {{{ getMemberFiles()
+
+ /**
+ * Get all the file data uploaded to a member into an array
+ *
+ * @return array member files
+ * @access protected
+ * @see Toolkit_FormBuilder::setupDefaults()
+ */
+ protected function getMemberFiles()
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE member_id = :id
+ ORDER BY id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->execute();
+
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $files[] = $row;
+ }
+ return $files;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ insertData()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param array $values Parameter description (if any) ...
+ * @param boolean $pending Parameter description (if any) ...
+ *
+ * @return object Return description (if any) ...
+ * @access public
+ */
+ public function insertData($values, $pending = false)
+ {
+ $cache = new Cache_Lite(Toolkit_Members::getCacheOptions());
+ $cache->remove("Member_Profile-{$_GET['id']}", 'Dynamic');
+
+ $insertData['name_on_disk'] = $values['uploaded_file_rmv'];
+ $insertData['member_id'] = $_GET['id'];
+ $insertData['size'] = $values['file_rmv']['size'];
+ $insertData['original_name'] = $values['file_rmv']['name'];
+ $insertData['file_name'] = $values['file_name'];
+ $insertData['pending'] = $pending;
+ try {
+ $params = implode(', ', array_keys($insertData));
+ $bindParams = ':' . implode(', :', array_keys($insertData));
+ $sql = "
+ INSERT INTO {$this->tableName} ($params)
+ VALUES ($bindParams)";
+ $stmt = $this->dbh->prepare($sql);
+ foreach ($insertData as $k => &$v) {
+ $metaData = $this->tableMetaData[$k];
+ if ($metaData == 'integer') {
+ $dataType = PDO::PARAM_INT;
+ } else if ($metaData == 'boolean') {
+ $dataType = PDO::PARAM_BOOL;
+ } else {
+ $dataType = PDO::PARAM_STR;
+ }
+ $stmt->bindParam(":$k", $v, $dataType);
+ }
+
+ return $stmt->execute();
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ processData()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param array $values Parameter description (if any) ...
+ *
+ * @return void
+ * @access public
+ */
+ public function processData($values)
+ {
+ Toolkit_Common::getTableMetaData();
+ $values['target'] = $this->findTargetFile($values);
+
+ if (array_key_exists('submitNewFile', $values)) {
+ $this->insertData($values);
+ } else {
+ $this->updateData($values);
+ }
+ $listPage = BASE_URL .
+ "admin/members.php?cat=2&subCat=2&tab=5&id={$_REQUEST['id']}";
+ header("Location: $listPage");
+ }
+
+ // }}}
+
+ // {{{ showFile()
+
+ /**
+ * Used in the template to determine when to show the File
+ *
+ * Since the file tag falls outside of the normal flow of the section loop
+ * we need to determine early if we should display the file or not. Since
+ * the file is the only element that uses a "static" quickform element,
+ * check to see if the first element type in a section is a static element
+ * and if so output the element (file).
+ *
+ * @param array $data The array of element objec
+ *
+ * @return boolean Whether an element is of type static or not.
+ * @access public
+ */
+ public function showFile($data)
+ {
+ return ($data->type == 'static');
+ }
+
+ // }}}
+
+ // {{{ updateData()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param array $values Parameter description (if any) ...
+ *
+ * @return mixed Return description (if any) ...
+ * @access public
+ */
+ public function updateData($values)
+ {
+ $cache = new Cache_Lite(Toolkit_Members::getCacheOptions());
+ $cache->remove("Member_Profile-{$_GET['id']}", 'Dynamic');
+
+ if (array_key_exists('delete', $values)) {
+ return $this->deleteFile($values);
+ }
+ $target = $values['target'];
+ foreach ($values as $k => $v) {
+ switch ($k) {
+ case "file_name$target" :
+ $values['file_name'] = $v;
+ unset($values[$k]);
+ break;
+
+ case "file$target" :
+ $pid = $v;
+ unset($values[$k]);
+ break;
+
+ default :
+ unset($values[$k]);
+ break;
+ }
+ }
+
+ try {
+ $params = array_keys($values);
+ $length = count($params);
+ for ($i = 0; $i < $length; ++$i) {
+ $bindParams .= "{$params[$i]} = :{$params[$i]}";
+ if ($i < ($length - 1)) {
+ $bindParams .= ', ';
+ }
+ }
+ $sql = "
+ UPDATE {$this->tableName}
+ SET $bindParams
+ WHERE id = :id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $pid, PDO::PARAM_INT);
+ foreach ($values as $k => $v) {
+ $metaData = $this->tableMetaData[$k];
+ if ($metaData == 'integer') {
+ $dataType = PDO::PARAM_INT;
+ } else if ($metaData == 'boolean') {
+ $dataType = PDO::PARAM_BOOL;
+ } else {
+ $dataType = PDO::PARAM_STR;
+ }
+ $stmt->bindParam(":$k", $values[$k], $dataType);
+ }
+ $stmt->execute();
+
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ return false;
+ }
+ return true;
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/EditMemberInfo.php b/Toolkit/Members/EditMemberInfo.php
new file mode 100644
index 0000000..3e67a47
--- /dev/null
+++ b/Toolkit/Members/EditMemberInfo.php
@@ -0,0 +1,3109 @@
+
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: EditMemberInfo.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+require_once BASE . 'Toolkit/Image/Server.php';
+
+/**
+ * Edit member info stored in the database
+ *
+ * Controls all aspects of creating and rendering the form used to manipulate
+ * the member data. Handles adding / editing module details, including:
+ * 1. Restaurants
+ * 2. Accommodations
+ * 3. Golfing
+ *
+ * Controls the addition of categories to a member record. Categories have
+ * dynamic settings which allow users to dynamically set which categories are
+ * associated to which modules (golf, accommodations, restaurant, etc...).
+ * Depending on which category is selected and assigned to a member record
+ * controls which modules are displayed on the form.
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com/admin/members.php?cat=2&subCat=2
+ * @see Toolkit_Members, member_admin
+ */
+class Toolkit_Members_EditMemberInfo
+ extends Toolkit_FormBuilder implements Toolkit_Form
+{
+ // {{{ properties
+
+ /**
+ * The Table name used to store the data of the member record in the database.
+ *
+ * @var string
+ * @access public
+ */
+ public $tableName = 'member';
+
+ /**
+ * Array of data that holds the meta data info on the table
+ *
+ * Contains information on the type of fields in the database.
+ * That way when we run our automated SQL queries with our PDO
+ * we can properly bind data to our SQL queries. This will
+ * allow for one more layer of protection against any sql
+ * injection attempts.
+ *
+ * @var string
+ * @access public
+ * @see Toolkit_Common::processData()
+ */
+ public $tableMetaData;
+
+ /**
+ * Determines if member updates have to be approved if changed
+ *
+ * If set to true, all module info must be approved by admin before it
+ * will be displayed on the front end to visitors. This also includes
+ * ccard information.
+ *
+ * Since all member forms will be spawned from this class, if we put
+ * this value here we can set once / change once and affect the entire
+ * app if we need to alter this. We can also set this up in any child
+ * class and override on individual classes if need be.
+ *
+ * @var string
+ * @access protected
+ */
+ protected $strictPending = true;
+
+ /**
+ * The table used to store the data of the member record in the database.
+ *
+ * @var string
+ * @access public
+ */
+ public $pendingTable = 'member_updates';
+
+ /**
+ * Determines if a member is in the pending state or not
+ *
+ * When the member has rows of data in the member_updates table in the DB
+ * they are considered "pending updates" until those changes are accepted
+ * or rejected by an admin user.
+ *
+ * @var string
+ * @access public
+ */
+ public $pending = false;
+
+ /**
+ * holds all the fields that are currently pending
+ *
+ * used in conjunction with the template, all fields that are in this
+ * list, will have a pending class for the
row, so they can easily
+ * be identified.
+ *
+ * @var string
+ * @access public
+ */
+ public $pendingFields = array();
+
+ // What are the modules associated with this form.
+ // New members won't have access to these right away.
+ // This boolean settings will be overridden inside the class.
+
+ /**
+ * The status of accommodation related categories associated w/ the member
+ *
+ * If the member has any categories that are assigned to the accommodations
+ * module, then this setting will become true and the form will show
+ * the accommodation module.
+ *
+ * @var bool
+ * @access protected
+ */
+ protected $accommodations = false;
+
+ /**
+ * The status of restaurant related categories associated w/ the member
+ *
+ * If the member has any categories that are assigned to the restaurant
+ * module, then this setting will become true and the form will show
+ * the restaurant module.
+ *
+ * @var bool
+ * @access protected
+ */
+ protected $restaurant = false;
+
+ /**
+ * The status of golf related categories associated w/ the member
+ *
+ * If the member has any categories that are assigned to the golf
+ * module, then this setting will become true and the form will show
+ * the golf module.
+ *
+ * @var bool
+ * @access protected
+ */
+ protected $golf = false;
+
+ /**
+ * States array for select list
+ *
+ * @var array
+ * @access protected
+ */
+ protected $states;
+
+ /**
+ * Category record objects
+ *
+ * Used when creating the category select list.
+ *
+ * @var array
+ * @access protected
+ */
+ protected $records = array();
+
+ /**
+ * The categories the member has associated with it
+ *
+ * @var array
+ * @access protected
+ */
+ protected $memberCategories = null;
+
+ /**
+ * Primary email address to send notification a record has been updated
+ *
+ * Set this value to false and it will turn off the email
+ * update notifications.
+ *
+ * @var string
+ * @access protected
+ */
+ protected $primaryAdvisee;
+
+ /**
+ * Email address of people that might also want to be advised of updates
+ *
+ * A list of all email address that might also want to be advised
+ * updates have been made on a business record. You can add as many
+ * as you would like and they will be CC in the email.
+ *
+ * N.B. You cannot make this array bigger than 5 people or you will need to
+ * rewrite the function to handle the server spam issue.
+ * @var array
+ * @access private
+ */
+ protected $secondaryAdvisees = array();
+
+ /**
+ * Flexy options used in the renderer
+ *
+ * @var array
+ * @access protected
+ */
+ protected $flexyOptions;
+
+ /**
+ * The name of the template used to render the business info form
+ *
+ * @var string
+ * @access protected
+ */
+ protected $formTemplate = 'editMember.tpl';
+
+ /**
+ * The name of the template used to email the owner for any updates
+ *
+ * When a member makes an update to thier record, this is the template
+ * we will use to send out the email notification to the site owner.
+ *
+ * @var string
+ * @access protected
+ */
+ protected $emailTemplate = 'emailOwner.tpl';
+
+ /**
+ * Message to return if the form successfully submits
+ *
+ * @var string
+ * @access protected
+ */
+ protected $successMsg = '
+
+ The information below has been successfully submitted.
+
';
+
+ /**
+ * The flexy template object which holds the rendered object
+ *
+ * @var object
+ * @access protected
+ */
+ protected $template;
+
+ /**
+ * Form access from inside the template
+ *
+ * @var object
+ * @access protected
+ */
+ protected $view;
+
+ /**
+ * Extra rules we need to register so we can fully validate form elements
+ *
+ * @var array
+ * @access protected
+ */
+ protected $registeredRules = array(
+ 'zip',
+ 'phone',
+ array(
+ 'checkEmail',
+ 'callback',
+ 'email',
+ 'Validate'
+ ),
+ array(
+ 'checkURI',
+ 'callback',
+ 'uri',
+ 'Validate'
+ )
+ );
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Class constructor
+ *
+ * @param PDO $pdo PHP Data Object to use for DB calls
+ * @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
+ * @see Toolkit_FormBuilder, HTML_QuickForm
+ */
+ public function __construct(
+ PDO $pdo,
+ $formName,
+ $method = 'post',
+ $action = '',
+ $target = '',
+ $attributes = null,
+ $trackSubmit = false
+ ) {
+ parent::__construct(
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+ // if this value is set to false, then no emails will be sent out
+ // upon update of a record.
+ if ($this->primaryAdvisee !== false) {
+ if (!defined('MEMBER_RECORD_UPDATES_ADVISOR')) {
+ // Please see property definition above for explanation.
+ echo 'in file: [' . __FILE__ . ' ] on line: [' . __LINE__ . '] ';
+ echo '
+
+ Please define the
+ MEMBER_RECORD_UPDATES_ADVISOR constant
+ in the setup file first.
This Constant should hold
+ the email address of the person you would like notified
+ when a member submits an update. Set to false if you do
+ not want an email to be sent.
+
+ Has updated thier business record and is now in a pending
+ state. To approve / reject thier changes you can either log
+ into your {$page->siteName} admin area or follow this
+ {$page->link}
+
";
+ $crlf = "\n";
+ $mimeMail = new Mail_mime($crlf);
+ $from = ereg_replace("[^A-Za-z ]", "", SITENAME) . ' <' . OWNER_EMAIL . '>';
+ $mimeMail->setFrom($from);
+ $mimeMail->setSubject('Member Record Update');
+ if (!empty($this->secondaryAdvisees)) {
+ foreach ($this->secondaryAdvisees as $k => $v) {
+ if (is_string($k) && !is_numeric($k)) {
+ $email = "$k <$v>";
+ } else {
+ $email = $v;
+ }
+ $mimeMail->addCC($email);
+ }
+ }
+ $mimeMail->setHTMLBody($htmlMsg);
+ $mimeMail->setTXTBody($msg);
+
+ $mail =& Mail::factory('mail');
+ $body = $mimeMail->get();
+ $headers = $mimeMail->headers($hdrs);
+
+ $res = $mail->send($this->primaryAdvisee, $headers, $body);
+ if (PEAR::isError($res)) {
+ return Toolkit_Common::handleError($res);
+ } else {
+ return $res;
+ }
+ }
+ }
+
+ // }}}
+
+ // {{{ fieldPending()
+
+ /**
+ * Determines if template fields are pending or not
+ *
+ * Each field in the template calls this function to determine if it
+ * is in a pending state or not. Fields that return true get a
+ * different colored background and border so they are easily recognizable.
+ *
+ * fields are considered pending if they are in the pendingFields array.
+ *
+ * @param string $elem element to check for pending
+ *
+ * @return boolean If the field is pending
+ * @access protected
+ */
+ public function fieldPending($elem)
+ {
+ if (!is_array($this->pendingFields)) {
+ return false;
+ } else {
+ return in_array($elem->name, $this->pendingFields);
+ }
+ }
+
+ // }}}
+ // {{{ filterURI()
+
+ /**
+ * Filters uri's before they are validated
+ *
+ * @param string $uri URI to filter
+ *
+ * @return mixed new uri if missing scheme
+ * @access
+ */
+ protected function filterURI($uri)
+ {
+ if (strstr($uri, 'http://') != $uri) {
+ return "http://$uri";
+ } else {
+ return $uri;
+ }
+ }
+
+ // }}}
+ // {{{ filterPhone()
+
+ /**
+ * Filters phone numbers before they are validated
+ *
+ * @param string $phone number to filter
+ *
+ * @return mixed newly formatted phone number
+ * @access
+ */
+ protected function filterPhone($phone)
+ {
+ // Ditch anything that is not a number
+ $number = preg_replace('/[^0-9]/', '', $phone);
+
+ // Invalid Number, validation will catch error
+ $len = strlen($number);
+ if (($len < 10) || ($len > 11)) {
+ return $phone;
+ }
+
+ // subscriber number
+ $sn = substr($number, -4);
+ // city code
+ $cc = substr($number, -7, 3);
+ // area code
+ $ac = substr($number, -10, 3);
+ if ($len == 11) {
+ // country prefix
+ $cp = $number[0];
+ }
+
+ $filteredNumber = "($ac) $cc-$sn";
+ if (!is_null($cp)) {
+ $filteredNumber = "$cp $filteredNumber";
+ }
+
+ return $filteredNumber;
+ }
+
+ // }}}
+
+ // {{{ generateLatLon()
+
+ /**
+ * Generates the listings lat and lon coordinates from either an address
+ * or their zip code. Depending on what gets entered into the form.
+ *
+ * If generating by zip code, we simply query the zip DB stored on ds3.
+ * Otherwise we query using google.
+ *
+ * @param mixed $data Array of data or zip
+ *
+ * @return Array Array of lat/lon coordinates
+ * @access protected
+ */
+ protected function generateLatLon($data)
+ {
+ if (is_array($data)) {
+ try {
+ // Since we don't store the city or state names we need to query
+ // for it really quick to get it.
+ $sql = "
+ SELECT state_name
+ FROM state s
+ WHERE state_id = :sid";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':sid', $data['state_id'], PDO::PARAM_INT);
+ $stmt->execute();
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ // Use google maps to get the lan/lon coords from our data.
+ $api_key = 'ABQIAAAAWqyv9sBAgUBdsdOdgo7LsRTeX7yNUukyMrmY8FsCXcCA9axlYBRmLDu7pJM7HIzM1e6MYO-pqjjp5w';
+ $addr = $values['street'];
+ $city = $values['city'];
+ $state = $row['state_name'];
+ $zip = $values['zip'];
+ $url = "http://maps.google.com/maps/geo?output=xml&key=$api_key&q=";
+ $q = "$addr, $city, $state, $zip";
+ $url .= urlencode($q);
+ // Query Google for this location's longitude and latitude
+ $command = "/usr/bin/curl '$url'";
+ exec($command, $output, $return);
+ if (preg_match_all("/(-?[0-9]{1,2}\.[0-9]{6})\,(-?[0-9]{1,2}\.[0-9]{6})\,0<\/coordinates>/", $output[0], $temp)) {
+ if (isset($temp[1][1])) {
+ $lon = $temp[1][1];
+ $lat = $temp[2][1];
+ } elseif (isset($temp[1][0])) {
+ $lon = $temp[1][0];
+ $lat = $temp[2][0];
+ } else {
+ $lat = 'NULL';
+ $lon = 'NULL';
+ }
+ }
+ $lat_lon['lat'] = $lat;
+ $lat_lon['lon'] = $lon;
+ return $lat_lon;
+ } else {
+ // We have a zip, just lookup in the db.
+ try {
+ $dsn = 'pgsql:host=ds3.gaslightmedia.com user=postgres dbname=zip';
+ $driverOptions = array(
+ PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
+ );
+ $zipPDO = new PDO($dsn, null, null, $driverOptions);
+ $zipPDO->setAttribute(
+ PDO::ATTR_ERRMODE,
+ PDO::ERRMODE_EXCEPTION
+ );
+
+ $sql = "
+ SELECT lat, lon
+ FROM zip
+ WHERE zipcode = :zip";
+ $stmt = $zipPDO->prepare($sql);
+ $stmt->bindParam(':zip', $data);
+ $stmt->execute();
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+ $return['lat'] = (float) $row['lat'];
+ $return['lon'] = (float) $row['lon'];
+ return $return;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+ }
+
+ // }}}
+ // {{{ getCategories()
+
+ /**
+ * Creates array structure of the category tree for use in a select element.
+ *
+ * This method will also instantiate a class property called tree for your
+ * class. This object will hold the tree structure of the categories list
+ * from the Database.
+ *
+ * @return array The array list of categories that can be loaded
+ * into a select element
+ *
+ * @access protected
+ * @see Toolkit_Members_CategoryTree
+ */
+ protected function getCategories()
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM category
+ WHERE parent_id = 0
+ ORDER BY name";
+ foreach ($this->dbh->query($sql, PDO::FETCH_ASSOC) as $row) {
+ $this->tree[] = new Toolkit_Members_CategoryTree($row['category_id'],
+ $row['name'],
+ $this->dbh);
+ }
+ if (!empty($this->tree)) {
+ foreach ($this->tree as $t) {
+ $this->createCategories($t);
+ }
+ }
+
+ if (empty($this->categories)) {
+ $this->categories = array('' => '-- No Categories Created Yet --');
+ } else {
+ $this->categories
+ = array('' => '-- Select Category --') + $this->categories;
+ }
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ getRegions()
+
+ /**
+ * Configure the regions for member stored in the database into an array
+ *
+ * @return array the regions
+ * @access protected
+ */
+ protected function getRegions()
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM region
+ ORDER BY region_name";
+ foreach ($this->dbh->query($sql) as $row) {
+ $regions[$row['region_id']] = $row['region_name'];
+ }
+ if (!empty($regions)) {
+ $regions = array('' => '-- Choose Region --') + $regions;
+ } else {
+ $regions = array('' => '-- No Regions Created Yet -- ');
+ }
+ return $regions;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ getCities()
+
+ /**
+ * Configure the cities for member stored in the database into an array
+ *
+ * @return array the cities
+ * @access protected
+ */
+ protected function getCities()
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM city
+ ORDER BY city_name";
+ foreach ($this->dbh->query($sql) as $row) {
+ $regions[$row['city_id']] = $row['city_name'];
+ }
+ if (!empty($regions)) {
+ $regions = array('' => '-- Choose City --') + $regions;
+ } else {
+ $regions = array('' => '-- No Cities Created Yet -- ');
+ }
+ return $regions;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ hasLogo()
+
+ /**
+ * Determine if the member record has a logo
+ *
+ * @return boolean if the record has a logo or not
+ * @access protected
+ */
+ protected function hasLogo()
+ {
+ try {
+ $member_id = $_GET['id'];
+
+ $sql = "
+ SELECT logo
+ FROM {$this->tableName}
+ WHERE member_id = :member_id";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $member_id, PDO::PARAM_INT);
+ $stmt->execute();
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ if (get_class($this) === 'Toolkit_Members_EditMemberOnlyInfo') {
+ $sql = "
+ SELECT count(*) AS total
+ FROM {$this->pendingTable}
+ WHERE member_id = :member_id
+ AND field = 'logo'";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $member_id, PDO::PARAM_INT);
+ $stmt->execute();
+ $pendingLogos = $stmt->fetch(PDO::FETCH_ASSOC);
+ }
+
+ $hasPending = !empty($pendingLogos['total']);
+ $hasLogo = !is_null($row['logo']);
+
+ return ($hasLogo || $hasPending);
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ inColumn2()
+
+ /**
+ * Lets the form know when to add a new column
+ *
+ * When rendering the form, we need to know what element
+ * to start rendering the new columns on, this function
+ * checks to see if we should start on the current
+ * element or not.
+ *
+ * This function is called from within the template.
+ *
+ * @param string $section element to check
+ *
+ * @return boolean if the section is in the 2nd column or not
+ * @access protected
+ */
+ public function inColumn2($section)
+ {
+ return ($this->formHeaders[$section]['col2']);
+ }
+
+ // }}}
+ // {{{ insertData()
+
+ /**
+ * Create a new record in the database from the data on the form
+ *
+ * When a member is first created, we don't have to worry about
+ * and module data ie.(golf, restaurant, accommodations), since
+ * they initially don't have any categories associated with them.
+ *
+ * Lat / Lon coordinates are not generated here, but they are
+ * injected into the form values if they are not filled in. This
+ * enables us to use google driving directions on all our members.
+ *
+ * Two groups of data are pulled from the values array of data.
+ * (categories & credit cards), these values are then unset in
+ * the values array, b/c we don't insert this data into the primary
+ * table. They each have their own table they get inserted into and
+ * are then associated to the newly inserted member.
+ *
+ * Empty field values are inserted as NULLS vs empty strings to allow
+ * for unique member_login names.
+ *
+ * A transaction is used to avoid orphaned data if any of the sql queries
+ * fail to properly insert the data.
+ *
+ * @param array $values Form values
+ *
+ * @return boolean False on error, True otherwise.
+ * @access public
+ */
+ public function insertData($values)
+ {
+ // {{{ Golfing
+
+ // Remove Golf Fields for Special Insert.
+ $fields = array(
+ 'par',
+ 'yardage',
+ 'course_rating',
+ 'slope_rating',
+ 'walking_course',
+ 'holes18',
+ 'holes9',
+ );
+
+ foreach ($fields as $v) {
+ $golfFields[$v] = $values[$v];
+ unset($values[$v]);
+ }
+
+ // }}}
+ // {{{ Accommodations
+
+ // Remove Accommodation Fields for Special Insert.
+ $fields = array(
+ 'reservation_id',
+ 'num_rooms',
+ 'year_round',
+ );
+ foreach ($fields as $v) {
+ $accommodationFields[$v] = $values[$v];
+ unset($values[$v]);
+ }
+
+ // }}}
+ // {{{ Restaurant
+
+ // Remove Restaurant Fields for Special Insert.
+ $fields = array(
+ 'breakfast',
+ 'breakfast_from',
+ 'breakfast_to',
+ 'brunch',
+ 'brunch_from',
+ 'brunch_to',
+ 'lunch',
+ 'lunch_from',
+ 'lunch_to',
+ 'dinner',
+ 'dinner_from',
+ 'dinner_to',
+ 'alcohol',
+ 'non_smoking',
+ );
+ foreach ($fields as $v) {
+ $restaurantFields[$v] = $values[$v];
+ unset($values[$v]);
+ }
+
+ // }}}
+
+ $ccards = $values['creditCards'];
+ $pattern = '/^-?(.+)$/i';
+ $replacement = '$1';
+ // Adjust the lat/lon coordinates to negative #'s if needed
+ // The only way this will be needed is if the lat/lon boxes
+ // were filled in instead of letting this class determine
+ // them via street address or zip code.
+ $coords = array('lat' => 'South', 'lon' => 'East');
+ foreach ($coords as $k => $v) {
+ if ($values["{$k}Direction"] == $v && !empty($values[$k])) {
+ $string = $values[$k];
+ $values[$k] = preg_replace($pattern, $replacement, $string);
+ $values[$k] = "-{$values[$k]}";
+ }
+ }
+ // If they dynamically add any categories, but then realize they
+ // want to remove them, they will show up in this array.
+ if (isset($values['removeCat'])) {
+ // So remove them before we get the categories to insert for the member.
+ $this->removeCategories($values['removeCat'], &$values['member_cats']);
+ }
+ // Now get the cats so we can insert them into a seperate table later.
+ $categories = $values['member_cats'];
+
+ // Unneeded data that will not be stored in the member table
+ unset($values['lonDirection'],
+ $values['latDirection'],
+ $values['member_cats'],
+ $values['removeCat'],
+ $values['creditCards']
+ );
+
+ try {
+ $params = implode(', ', array_keys($values));
+ $bindParams = ':' . implode(', :', array_keys($values));
+ $sql = "
+ INSERT INTO {$this->tableName} ($params)
+ VALUES ($bindParams)
+ RETURNING member_id";
+ $this->dbh->beginTransaction();
+ $stmt = $this->dbh->prepare($sql);
+ foreach ($values as $k => &$v) {
+ $metaData = $this->tableMetaData[$k];
+ if ($metaData == 'integer') {
+ $dataType = PDO::PARAM_INT;
+ } elseif ($metaData == 'boolean') {
+ $dataType = PDO::PARAM_BOOL;
+ } else {
+ $dataType = PDO::PARAM_STR;
+ }
+ // for empty values that are not actually a zero (0), we
+ // want to insert null's.
+ // This will help hold the unique values for member_logins,
+ // as empty values '', are not considered unique
+ if (empty($v) && $v !== 0) {
+ $v = null;
+ $dataType = PDO::PARAM_NULL;
+ }
+ $stmt->bindParam(":$k", $v, $dataType);
+ }
+ $stmt->execute();
+ $stmt->bindColumn('member_id', $mid);
+ $stmt->fetch();
+
+ // Insert the categories into the DB and associate
+ // them w/ the newly inserted member.
+ if (!empty($categories)) {
+ $sql = "
+ INSERT INTO member_category(member_id, category_id)
+ VALUES(:member_id, :cid)";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $mid, PDO::PARAM_INT);
+ foreach ($categories as $cid) {
+ // If the user didn't select a category,
+ // Then don't run an insert query.
+ if (!empty($cid)) {
+ $stmt->bindParam(':cid', $cid, PDO::PARAM_INT);
+ $stmt->execute();
+ }
+ }
+ }
+
+ // Insert the members credit cards into the DB and associate
+ // the w/ our new member. We get the ccard ID # by querying for
+ // it in the ccard_type table by the ccard name.
+ if (!empty($ccards)) {
+ $sql = "
+ INSERT INTO member_ccard_type(member_id, ccard_type_id)
+ SELECT :member_id, ccard_type_id
+ FROM ccard_type
+ WHERE ccard_type_name = :cctn";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $mid, PDO::PARAM_INT);
+ foreach ($ccards as $k => $v) {
+ $stmt->bindParam(':cctn', $k, PDO::PARAM_STR);
+ $stmt->execute();
+ }
+ }
+
+ $golf = $restaurant = $accommodations = false;
+ if (!empty($categories)) {
+ $sql = "
+ SELECT *
+ FROM category
+ WHERE category_id = :cid";
+ $stmt = $this->dbh->prepare($sql);
+ foreach ($categories as &$cid) {
+ if (!empty($cid)) {
+ $stmt->bindParam(':cid', $cid, PDO::PARAM_INT);
+ $stmt->execute();
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+ // If any of the module statuses are true, set them.
+ // otherwise leave them as they were, (we don't want
+ // to set a true back to a false).
+ $golf = ($row['golf'] == 't') ? true : $golf;
+ $accommodations = ($row['accommodations'] == 't') ?
+ true : $accommodations;
+ $restaurant = ($row['restaurant'] == 't') ?
+ true : $restaurant;
+ }
+ }
+ }
+ $this->clearModule('member_golf');
+ if ($golf) {
+ $this->updateModuleFields($golfFields, 'member_golf', $mid);
+ }
+ $this->clearModule('member_accommodations');
+ if ($accommodations) {
+ $this->updateModuleFields($accommodationFields, 'member_accommodations', $mid);
+ }
+ $this->clearModule('member_restaurants');
+ if ($restaurant) {
+ $this->updateModuleFields($restaurantFields, 'member_restaurants', $mid);
+ }
+ $this->dbh->commit();
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ header('Location: ' . BASE_URL . "admin/members.php?cat=2&subCat=2&tab=1&id=$mid");
+ return true;
+ }
+
+ // }}}
+
+ // {{{ newColumn()
+
+ /**
+ * Determines if we've reached the field that should start a new column
+ *
+ * This is used from the Flexy template. Each field name is passed into
+ * this function, when we reach the appropriate field, we will know that
+ * we need to start a new column.
+ *
+ * @param string $string The name of the field we're checking.
+ *
+ * @return boolean True on the right field, otherwise false.
+ * @access protected
+ */
+ public function newColumn($string)
+ {
+ return ($string == 'Account Info');
+ }
+
+ // }}}
+
+ // {{{ processData()
+
+ /**
+ * Handles processing the submitted forms data.
+ *
+ * Sets up the table meta data so we can insert into the member table.
+ * removes any unwanted fields from the values array. these fields
+ * will be denoted by the '_rmv' at the end of thier name in the
+ * configureElements function
+ *
+ *
+ * ... 'name' => 'remove_rmv', ...
+ *
+ *
+ * This function also verifies that the lat/lon values were properly filled
+ * out, if they were left blank then the values will either be looked up
+ * via google maps or through our own zip DB. These values will then be
+ * inserted into the values array AND also injected into the form field
+ * values so they will display when the form comes back around.
+ *
+ * The form then decides if it is handeling a new member or not and calls
+ * the appropriate function to insert or update data.
+ *
+ * @param array $values The array of all submitted form values.
+ *
+ * @return boolean Whether the insert/update succeeded.
+ * @access public
+ */
+ public function processData($values)
+ {
+ // Clean up some form elements before we try any processing
+ if (is_array($values['join_date'])) {
+ if (is_numeric($values['join_date']['m'])) {
+ $values['join_date'] = implode('-', $values['join_date']);
+ } else {
+ $values['join_date'] = null;
+ }
+ }
+ $this->processLogo(&$values);
+ Toolkit_Common::getTableMetaData();
+
+ foreach ($values as $k => $v) {
+ switch ($k) {
+ case 'MAX_FILE_SIZE' :
+ unset($values[$k]);
+ break;
+
+ default :
+ if (preg_match('/^.+_rmv$/', $k)) {
+ unset($values[$k]);
+ }
+ break;
+ }
+ }
+
+ //$this->verifyLatLon(&$values);
+
+ $existingMember = (is_numeric($_GET['id']));
+ if ($existingMember) {
+ return $this->updateData($values);
+ } else {
+ return $this->insertData($values);
+ }
+ }
+
+ // }}}
+
+ // {{{ processLogo()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param array $values Parameter description (if any) ...
+ *
+ * @return object Return description (if any) ...
+ * @access protected
+ */
+ protected function processLogo($values)
+ {
+ // Keep a tidy house.
+ // There are 2 scenarios to deal w/ logos:
+ // 1. Removing logo:
+ // Delete the image from the image server
+ // and set the values['logo'] to null.
+ // 2. New logo:
+ // Check to see if old_logo_rmv holds a value,
+ // if it does then remove that logo
+ // Upload the image and put new filename
+ // into values['logo'] variable.
+ $imgServer = new Toolkit_Image_Server();
+
+ if ($values['remove_logo_rmv'] == 1) {
+ $imgServer->imageDelete($values['old_logo_rmv']);
+ $values['logo'] = null;
+
+ if (get_class($this) == 'Toolkit_Members_EditMemberOnlyInfo') {
+ try {
+ // Make sure any logos that were pending are removed as well.
+ $sql = "
+ DELETE FROM {$this->pendingTable}
+ WHERE field = 'logo'
+ AND member_id = :member_id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->execute();
+
+ $sql = "
+ UPDATE {$this->tableName}
+ SET logo = :logo
+ WHERE member_id = :member_id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':logo', $values['logo'], PDO::PARAM_NULL);
+ $stmt->bindParam(':member_id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->execute();
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+ }
+
+ // If a new logo is uploaded, have the image server
+ // process that logo and give us back the file name on
+ // the server.
+ if ($values['new_logo_rmv']['size'] > 0) {
+ $imgName = $imgServer->imageUpload('new_logo_rmv');
+ $values['logo'] = $imgName;
+ $img = '';
+
+ // If the old_logo_rmv key is set and not empty
+ // then we are replacing an existing logo and did not
+ // check the remove logo checkbox.
+ // remove this old logo just for good house keeping.
+ if (isset($values['old_logo_rmv']) && !empty($values['old_logo_rmv'])) {
+ $imgServer->imageDelete($values['old_logo_rmv']);
+ // update the elements on the form if we are replacing an existing logo.
+ if ($this->elementExists('old_logo_rmv')) {
+ $e =& $this->getElement('old_logo_rmv');
+ $e->setValue($imgName);
+ }
+ if ($this->elementExists('image_rmv')) {
+ $e =& $this->getElement('image_rmv');
+ $e->setValue($img);
+ }
+ } else {
+ $source =& $this->createElement(
+ 'checkbox',
+ 'remove_logo_rmv',
+ 'Remove Logo'
+ );
+ $this->insertElementBefore($source, 'new_logo_rmv');
+
+ $source =& $this->addElement('hidden', 'old_logo_rmv');
+ $source->setValue($imgName);
+
+ $source =& $this->createElement(
+ 'static',
+ 'image_rmv',
+ 'Current Logo'
+ );
+ $source->setValue($img);
+ $element = $this->insertElementBefore($source, 'new_logo_rmv');
+
+ if (PEAR::isError($element)) {
+ die ('there was an error uploading your file!');
+ } else {
+ // I don't know why, but the insertElementBefore
+ // function was erasing the value we set earlier.
+ // so just reset it to make double sure its there.
+ $element->setValue($img);
+ }
+ }
+ }
+
+ // We clicked to remove the logo and did not upload a new one.
+ if ($values['remove_logo_rmv'] == 1 && $values['new_logo_rmv']['size'] == 0) {
+ if ($this->elementExists('remove_logo_rmv')) {
+ $this->removeElement('remove_logo_rmv', false);
+ }
+ if ($this->elementExists('image_rmv')) {
+ $this->removeElement('image_rmv', false);
+ }
+ if ($this->elementExists('old_logo_rmv')) {
+ $this->removeElement('old_logo_rmv', false);
+ }
+ }
+ }
+
+ // }}}
+
+ // {{{ removeCategories()
+
+ /**
+ * Remove categories from the values['member_cats'] array
+ *
+ * Any values in the removeCats array are removed from the
+ * values['member_cats'] array which is passed in by reference
+ * so we don't have to return any values.
+ *
+ * @param array $targets All the category id's we want to remove
+ * @param array &$values All the categories submitte.
+ *
+ * @return void
+ * @access protected
+ */
+ protected function removeCategories($targets, &$values)
+ {
+ foreach ($targets as $cid) {
+ $key = array_search($cid, $values);
+ unset($values[$key]);
+ }
+ }
+
+ // }}}
+
+ // {{{ setConfig()
+
+ /**
+ * Sets the query to use to fetch the datagrid results
+ *
+ * @param Config_Container $c Configuration object
+ *
+ * @return void
+ * @access public
+ */
+ public function setConfig(Config_Container $c)
+ {
+ $this->config = $c;
+ }
+
+ // }}}
+ // {{{ setStates()
+
+ /**
+ * Set the states available for the form
+ *
+ * @param array $states Array of states available for the form
+ *
+ * @return void
+ * @access public
+ */
+ public function setStates(array $states)
+ {
+ $this->states = $states;
+ }
+
+ // }}}
+ // {{{ setupFormCategories()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupFormCategories()
+ {
+ try {
+ // Determine if this is a new member record or we're editing
+ // an existing member record.
+ $member_id = $_GET['id'];
+ // Get all the categories already associated w/ this member.
+ // This part is primarily for editing existing members.
+ // That way they categories initially show up.
+ // They are ordered by the mem_cat_id which should keep
+ // them in the same order as they were added.
+ $sql = "
+ SELECT *
+ FROM member_category
+ WHERE member_id = :id
+ ORDER BY member_category_id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $member_id, PDO::PARAM_INT);
+ $stmt->execute();
+
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $memCats[$row['category_id']] = true;
+ }
+
+ // If we submitted the form:
+ // 1. Get all the member_cat values on the form that were submitted.
+ // If we flip the key/value pairs when we add the submitted values
+ // we won't have to worry about checking for duplicate cats submitted.
+ // 2. If we clicked on a remove button determine the x/y coords
+ // (hint: the coords will be empty if we didn't click on one).
+ // if the coords are not empty, then remove the category we clicked
+ // on, it will be the removeCat form element.
+ if ($this->isSubmitted()) {
+ if (!is_array($memCats)) {
+ $memCats = array();
+ }
+ $submittedMemberCats = $this->getSubmitValue('member_cats');
+ if (is_array($submittedMemberCats) && !empty($submittedMemberCats)) {
+ $memCats += array_flip($this->getSubmitValue('member_cats'));
+ }
+ // Holds a possible array of category id's we want to remove.
+ $removeTargets = $this->getSubmitValue('removeCat');
+ // If the array is not empty, then scoot through it and remove
+ // any of the categories form the memCats array so they won't
+ // show up again.
+ if (!empty($removeTargets)) {
+ foreach ($removeTargets as $k => $v) {
+ unset($memCats[$v]);
+ }
+ }
+ }
+
+ // Unset the blank key so the sql query doesn't puke when trying to
+ // add it into the DB. The blank key will occur if no cat is selected.
+ // its the default option for the select list.
+ unset($memCats['']);
+ $this->memberCategories = $memCats;
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ setupRenderers()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ $renderer =& new HTML_QuickForm_Renderer_Object(true);
+
+ $this->accept($renderer);
+
+ $this->template =& new HTML_Template_Flexy($this->flexyOptions);
+
+ $m = new Toolkit_Members_RecordNavigation($this->config);
+ $m->setupAdminNavStructure();
+ // Make the view a copy of the $this object
+ // That way we have access to call functions in
+ // this class from within the template.
+ $this->view = $this;
+ $this->view->baseUrl = BASE_URL;
+ $this->view->form = $renderer->toObject();
+ $this->view->nav = $m->getPageNav();
+ $this->template->compile($this->formTemplate);
+ }
+
+ // }}}
+ // {{{ showCategories()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @return string Return description (if any) ...
+ * @access public
+ */
+ public function showCategories()
+ {
+ if (!empty($this->memberCategories)) {
+ try {
+ $sql = "
+ SELECT *
+ FROM category
+ WHERE category_id = :cid";
+ $stmt = $this->dbh->prepare($sql);
+ foreach ($this->memberCategories as $cid => $v) {
+ $stmt->bindParam(':cid', $cid, PDO::PARAM_INT);
+ $stmt->execute();
+ $category = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ $out .= '
+
+
+
+ '.$category['name'].'
+ ';
+ }
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ return $out;
+ }
+
+ // }}}
+
+ // {{{ toHTML()
+
+ /**
+ * Renders the form
+ *
+ * sets the page the form should be redirected to instead of coming back
+ * around to itself.
+ *
+ * @return string The rendered form
+ * @access public
+ */
+ public function toHTML()
+ {
+ // We need to validate (and freeze if needed)
+ // before we render the form. That way the
+ // template knows about any errors on the form.
+ $this->validated = $this->validate();
+ if ($this->validated) {
+ $processed = $this->process(array(&$this, 'processData'), $this->mergeFiles);
+ }
+
+ // ProcessData handles settingup the lat/lon coordinates if they were not entered
+ // into the form. these values ar calculated and then inserted into the forms
+ // element values. So we need to process the data first and then render the form.
+ $this->setupRenderers();
+
+ return $this->template->bufferedOutputObject($this->view);
+ }
+
+ // }}}
+
+ // {{{ updateData()
+
+ /**
+ * Update the record data
+ *
+ * @param array $values scrubbed values submitted from the form
+ *
+ * @return object True on success
+ * @access public
+ */
+ public function updateData($values)
+ {
+ /*
+ // Remove any cache we have for this member so the next
+ // page load of that member profile will generate new content.
+ $cache = new Cache_Lite(Toolkit_Members::getCacheOptions());
+ $cache->remove("Member-{$_GET['id']}", 'Dynamic');
+ */
+
+ $member_id = $_GET['id'];
+ // {{{ Golfing
+
+ // Remove Golf Fields for Special Insert.
+ $fields = array(
+ 'par',
+ 'yardage',
+ 'course_rating',
+ 'slope_rating',
+ 'walking_course',
+ 'holes18',
+ 'holes9',
+ );
+
+ foreach ($fields as $v) {
+ $golfFields[$v] = $values[$v];
+ unset($values[$v]);
+ }
+
+ // }}}
+ // {{{ Accommodations
+
+ // Remove Accommodation Fields for Special Insert.
+ $fields = array(
+ 'reservation_id',
+ 'num_rooms',
+ 'year_round',
+ );
+ foreach ($fields as $v) {
+ $accommodationFields[$v] = $values[$v];
+ unset($values[$v]);
+ }
+
+ // }}}
+ // {{{ Restaurant
+
+ // Remove Restaurant Fields for Special Insert.
+ $fields = array(
+ 'breakfast',
+ 'breakfast_from',
+ 'breakfast_to',
+ 'brunch',
+ 'brunch_from',
+ 'brunch_to',
+ 'lunch',
+ 'lunch_from',
+ 'lunch_to',
+ 'dinner',
+ 'dinner_from',
+ 'dinner_to',
+ 'alcohol',
+ 'non_smoking',
+ );
+ foreach ($fields as $v) {
+ $restaurantFields[$v] = $values[$v];
+ unset($values[$v]);
+ }
+
+ // }}}
+
+ // Remove values not wanted before we get all the member categories.
+ if (isset($values['removeCat'])) {
+ // So remove them before we get the categories to insert for the member.
+ $this->removeCategories($values['removeCat'], &$values['member_cats']);
+ }
+ // Now get the cats so we can insert them into a seperate table later.
+ $categories = $values['member_cats'];
+
+ $ccards = $values['creditCards'];
+ $pattern = '/^-?(.+)$/i';
+ $replacement = '$1';
+ // Adjust the lat/lon coordinates to negative #'s if needed
+ $coords = array('lat' => 'South', 'lon' => 'East');
+ foreach ($coords as $k => $v) {
+ if ($values["{$k}Direction"] == $v && !empty($values[$k])) {
+ $string = $values[$k];
+ $values[$k] = preg_replace($pattern, $replacement, $string);
+ $values[$k] = "-{$values[$k]}";
+ }
+ }
+ unset($values['lonDirection'],
+ $values['latDirection'],
+ $values['member_cats'],
+ $values['removeCat'],
+ $values['creditCards']
+ );
+
+ try {
+ $params = array_keys($values);
+ $length = count($params);
+ for ($i = 0; $i < $length; ++$i) {
+ $bindParams .= "{$params[$i]} = :{$params[$i]}";
+ if ($i < ($length - 1)) {
+ $bindParams .= ', ';
+ }
+ }
+ $this->dbh->beginTransaction();
+ $sql = "
+ UPDATE {$this->tableName}
+ SET $bindParams
+ WHERE member_id = :member_id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $member_id, PDO::PARAM_INT);
+ foreach ($values as $k => &$v) {
+ $metaData = $this->tableMetaData[$k];
+ if ($metaData == 'integer') {
+ $dataType = PDO::PARAM_INT;
+ } else if ($metaData == 'boolean') {
+ $dataType = PDO::PARAM_BOOL;
+ } else {
+ $dataType = PDO::PARAM_STR;
+ }
+ // for empty values that are not actually a zero (0), we
+ // want to insert null's.
+ // This will help hold the unique values for member_logins,
+ // as empty values '', are not considered unique
+ if (empty($v) && $v !== 0) {
+ $v = null;
+ $dataType = PDO::PARAM_NULL;
+ }
+ $stmt->bindParam(":$k", $v, $dataType);
+ }
+ $stmt->execute();
+
+ // Handle updating the credit cards
+ $sql = "
+ DELETE FROM member_ccard_type
+ WHERE member_id = :id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $member_id, PDO::PARAM_INT);
+ $stmt->execute();
+
+ if (is_array($ccards)) {
+ $sql = "
+ INSERT INTO member_ccard_type (member_id, ccard_type_id)
+ SELECT :id, ccard_type_id
+ FROM ccard_type
+ WHERE ccard_type_name = :cctn";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $member_id, PDO::PARAM_INT);
+ foreach ($ccards as $k => &$v) {
+ if ($v) {
+ $stmt->bindParam(':cctn', $k, PDO::PARAM_STR);
+ $stmt->execute();
+ }
+ }
+ }
+
+ // Handle updating the categories
+ $sql = "
+ DELETE FROM member_category
+ WHERE member_id = :id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $member_id, PDO::PARAM_INT);
+ $stmt->execute();
+
+ if (is_array($categories)) {
+ $sql = "
+ INSERT INTO member_category (member_id, category_id)
+ VALUES (:member_id, :cid)";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $member_id, PDO::PARAM_INT);
+ foreach ($categories as &$cid) {
+ if (!empty($cid)) {
+ $stmt->bindParam(':cid', $cid, PDO::PARAM_INT);
+ $stmt->execute();
+ }
+ }
+ }
+
+ $golf = $restaurant = $accommodations = false;
+ if (!empty($categories)) {
+ $sql = "
+ SELECT *
+ FROM category
+ WHERE category_id = :cid";
+ $stmt = $this->dbh->prepare($sql);
+ foreach ($categories as &$cid) {
+ if (!empty($cid)) {
+ $stmt->bindParam(':cid', $cid, PDO::PARAM_INT);
+ $stmt->execute();
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+ // If any of the module statuses are true, set them.
+ // otherwise leave them as they were, (we don't want
+ // to set a true back to a false).
+ $golf = ($row['golf'] == 't') ? true : $golf;
+ $accommodations = ($row['accommodations'] == 't') ?
+ true : $accommodations;
+ $restaurant = ($row['restaurant'] == 't') ?
+ true : $restaurant;
+ }
+ }
+ }
+ $this->clearModule('member_golf');
+ if ($golf) {
+ $this->updateModuleFields($golfFields, 'member_golf');
+ }
+ $this->clearModule('member_accommodations');
+ if ($accommodations) {
+ $this->updateModuleFields($accommodationFields, 'member_accommodations');
+ }
+ $this->clearModule('member_restaurants');
+ if ($restaurant) {
+ $this->updateModuleFields($restaurantFields, 'member_restaurants');
+ }
+
+ $cache = new Cache_Lite(Toolkit_Members::getCacheOptions());
+ $cache->remove("Member_Profile-{$_GET['id']}", 'Dynamic');
+
+ return $this->dbh->commit();
+ } catch (PDOException $e) {
+ $this->dbh->rollBack();
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ updateModuleFields()
+
+ // member_id in the params is for inserting the data if the form fails validation
+ // first and comes back around and module categories will be included on the form
+ // and you need to be able to insert the data and associate to the member.
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param array $values Parameter description (if any) ...
+ * @param unknown $tableName Parameter description (if any) ...
+ * @param unknown $member_id Parameter description (if any) ...
+ *
+ * @return object Return description (if any) ...
+ * @access protected
+ */
+ protected function updateModuleFields($values, $tableName, $member_id = null)
+ {
+ Toolkit_Common::getTableMetaData(null, $tableName);
+ $values['member_id'] = (!is_null($member_id)) ? $member_id : $_GET['id'];
+ try {
+ $params = implode(', ', array_keys($values));
+ $bindParams = ':' . implode(', :', array_keys($values));
+ $sql = "
+ INSERT INTO $tableName ($params)
+ VALUES ($bindParams)";
+ $stmt = $this->dbh->prepare($sql);
+ foreach ($values as $k => &$v) {
+ $metaData = $this->tableMetaData[$k];
+ if ($metaData == 'integer') {
+ $dataType = PDO::PARAM_INT;
+ } else if ($metaData == 'boolean') {
+ $dataType = PDO::PARAM_BOOL;
+ } else {
+ $dataType = PDO::PARAM_STR;
+ }
+ // for empty values that are not actually a zero (0), we
+ // want to insert null's.
+ // This will help hold the unique values for member_logins,
+ // as empty values '', are not considered unique
+ if (empty($v) && $v !== 0) {
+ $v = null;
+ $dataType = PDO::PARAM_NULL;
+ }
+ $stmt->bindParam(":$k", $v, $dataType);
+ }
+ return $stmt->execute();
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ validated()
+
+ /**
+ * Checks if the form is validated
+ *
+ * If the form is validated display the success msg.
+ * If the form is submitted but not validated, display
+ * the error msg. Other wise display nothing.
+ *
+ * This function is called from within the template.
+ *
+ * @return string The success or error msg for the user.
+ * @access protected
+ */
+ public function validated()
+ {
+ if ($this->validated) {
+ return $this->successMsg;
+ } elseif ($this->isSubmitted()) {
+ return $this->errorMsg;
+ }
+ }
+
+ // }}}
+ // {{{ verifyLatLon()
+
+ /**
+ * Adjust lat / lon values on form if needed
+ *
+ * Checks to make sure the latitude and longitude values are present on the form.
+ * If either one is empty, it calculates the coordinates from the given data on the
+ * and inserts or updates the form element values.
+ *
+ * @param array $values lat/lon values
+ *
+ * @return string The rendered form
+ * @access protected
+ */
+ protected function verifyLatLon($values)
+ {
+ if (empty($values['lat']) || empty($values['lon'])) {
+ if (!empty($values['street'])) {
+ $coords = $this->generateLatLon(&$values);
+ } else {
+ $coords = $this->generateLatLon($values['zip']);
+ }
+ }
+
+ // Set each lat and lon value if its not empty.
+ // insert the value back into the forms GROUPED element.
+ if (!empty($coords['lat'])) {
+ $values['lat'] = $coords['lat'];
+ $e =& $this->getElement('lat');
+ $e->setValue($coords['lat']);
+ }
+ if (!empty($coords['lon'])) {
+ $values['lon'] = $coords['lon'];
+ $e =& $this->getElement('lon');
+ $e->setValue($coords['lon']);
+ }
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/EditMemberOnlyAmenities.php b/Toolkit/Members/EditMemberOnlyAmenities.php
new file mode 100644
index 0000000..77817b4
--- /dev/null
+++ b/Toolkit/Members/EditMemberOnlyAmenities.php
@@ -0,0 +1,451 @@
+
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: EditMemberOnlyAmenities.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Short description for class
+ *
+ * Long description (if any) ...
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Members_EditMemberOnlyAmenities
+ extends Toolkit_Members_EditMemberAmenities implements Toolkit_Form
+{
+ // {{{ properties
+
+ /**
+ * All the default data
+ *
+ * When we load the default data (member record from the database), we will
+ * store all that data in this variable. That way when we process the form
+ * we will have all the information to compare against, so we can find the
+ * updates.
+ *
+ * @var string
+ * @access protected
+ */
+ protected $oldData;
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Class constructor
+ *
+ * @param PDO $pdo PHP Data Object to use for DB calls
+ * @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
+ * @see Toolkit_Members_EditMemberInfo
+ */
+ public function __construct(
+ PDO $pdo,
+ $formName,
+ $method = 'post',
+ $action = '',
+ $target = '',
+ $attributes = null,
+ $trackSubmit = false
+ ) {
+ parent::__construct(
+ $pdo,
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+ $this->setPending();
+ }
+
+ // }}}
+
+ // {{{ createPendingData()
+
+ /**
+ * Make any changes into a pending state
+ *
+ * If strict pending is turned on, any changes that were made will
+ * have to fall into a pending state. to do that we need to drop
+ * any update into the updates table.
+ *
+ * @param array $values submitted form values
+ *
+ * @return boolean
+ * @access Protected
+ */
+ protected function createPendingData($values)
+ {
+ try {
+ $this->handleReconsiderations(&$values);
+ // Find out all the amenities the member currently has.
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE member_id = :member_id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->execute();
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $currentAmenities[] = $row['amenity_id'];
+ }
+
+ // If they have no amenities already, we need to make sure
+ // this variable is at least defined as an array so
+ // we can get the array_diff.
+ if (empty($currentAmenities)) {
+ $currentAmenities = array();
+ }
+ // Find out all the new amenities that where added.
+ $alteredAmenities
+ = array_diff(array_keys($values), $currentAmenities);
+
+ $sql = "
+ SELECT *
+ FROM amenity
+ WHERE amenity_id = :aid";
+ $fetchStmt = $this->dbh->prepare($sql);
+ $sql = "
+ INSERT INTO member_updates (update, data_type, member_id, field,
+ db_table, label)
+ VALUES (:update, 'string', :member_id, :field, :table, :label)";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->bindParam(':table', $this->tableName, PDO::PARAM_STR);
+ // If any amenities where added
+ // insert them into the updates table to be in a pending state.
+ if (!empty($alteredAmenities)) {
+ $update = 1;
+ $stmt->bindParam(':update', $update, PDO::PARAM_STR);
+ foreach ($alteredAmenities as $k => &$v) {
+ $fetchStmt->bindParam(':aid', $v, PDO::PARAM_INT);
+ $fetchStmt->execute();
+ $row = $fetchStmt->fetch(PDO::FETCH_ASSOC);
+
+ $stmt->bindParam(':label', $row['amenity_name'], PDO::PARAM_STR);
+ $stmt->bindParam(':field', $v, PDO::PARAM_STR);
+ $stmt->execute();
+ }
+ }
+
+ $update = 0;
+ // If any amenities are removed
+ // insert the removal request into the updates table
+ // so it can be in a pending state.
+ foreach ($currentAmenities as $k => &$v) {
+ if (!array_key_exists($v, $values)) {
+ $fetchStmt->bindParam(':aid', $v, PDO::PARAM_INT);
+ $fetchStmt->execute();
+ $row = $fetchStmt->fetch(PDO::FETCH_ASSOC);
+
+ $stmt->bindParam(':update', $update, PDO::PARAM_STR);
+ $stmt->bindParam(':label', $row['amenity_name'], PDO::PARAM_STR);
+ $stmt->bindParam(':field', $v, PDO::PARAM_STR);
+ $stmt->execute();
+ }
+ }
+
+ return true;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ configureDefaults()
+
+ /**
+ * Loads default values for the form
+ *
+ * Setup the members default values to load into the form.
+ * Copy all these values, which is the old data we will use to compare
+ * against when the form is submitted to determine the updates, into
+ * the oldData variable.
+ *
+ * @return void
+ * @access protected
+ */
+ public function configureDefaults()
+ {
+ $this->oldData = parent::configureDefaults();
+
+ try {
+ $sql = "
+ SELECT field, 'update'
+ FROM member_updates
+ WHERE id in (
+ SELECT max(id)
+ FROM member_updates
+ GROUP BY field)
+ AND member_id = :member_id
+ AND db_table = '{$this->tableName}'";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->execute();
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $this->oldData[$row['field']] = $row['update'];
+ }
+ $this->setupDefaults($this->oldData);
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ fieldPending()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param object $elem Parameter description (if any) ...
+ *
+ * @return mixed Return description (if any) ...
+ * @access public
+ */
+ public function fieldPending($elem)
+ {
+ if (!is_array($this->pendingFields)) {
+ return false;
+ } else {
+ return in_array($elem->label, $this->pendingFields);
+ }
+ }
+
+ // }}}
+
+ // {{{ handleReconsiderations()
+
+ /**
+ * Makes amenities not pending anymore if they get re-added or re-removed
+ *
+ * These two cases both reset the field to its previous state before
+ * the original request was made. So it bypasses the need of an admin
+ * to approve or reject the request, removes the fields from the updates
+ * table, and resets the field to its state before the request was made.
+ *
+ * If an amenity was added and removed before the admin has the ability
+ * to approve the request, we remove the field from the updates table
+ * and reset the pending field. Same happens if an amenity is removed
+ * and added back in before the admin approves the removal request.
+ *
+ * @param mixed $values array of values submitted from the form.
+ *
+ * @return void
+ * @access public
+ */
+ protected function handleReconsiderations($values)
+ {
+ // Get all the latest updates for this member's amenities.
+ $sql = "
+ SELECT *
+ FROM member_updates
+ WHERE id IN (
+ SELECT max(id)
+ FROM member_updates
+ WHERE member_id = :member_id
+ GROUP BY field)
+ AND db_table = '{$this->tableName}'";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->execute();
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $updates[$row['field']] = $row;
+ }
+
+ // Set up the query to remove an amenity.
+ $sql = "
+ DELETE FROM member_updates
+ WHERE field = :field
+ AND db_table = '{$this->tableName}'
+ AND member_id = :member_id";
+ $delStmt = $this->dbh->prepare($sql);
+ $delStmt->bindParam(':member_id', $_GET['id'], PDO::PARAM_INT);
+ // This case can only happen if there are updates pending.
+ // If any amenities were re-added or re-removed, then remove
+ // them from the updates table cause they went back to their
+ // original state.
+ if (!empty($updates)) {
+ $updateableAmenities = array_keys($updates);
+ foreach ($updateableAmenities as $k => &$v) {
+ $keyExists = array_key_exists($v, $values);
+ $adding = (bool) $updates[$v]['update'];
+ // Removed then added back in.
+ $reAdded = (!$keyExists && $adding) ? true : false;
+ // Added then removed again.
+ $reRemoved = ($keyExists && !$adding) ? true : false;
+
+ if ($reAdded || $reRemoved) {
+ $delStmt->bindParam(':field', $v, PDO::PARAM_INT);
+ $delStmt->execute();
+ }
+ }
+ }
+ }
+
+ // }}}
+
+ // {{{ processData()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param array $values Parameter description (if any) ...
+ *
+ * @return void
+ * @access public
+ */
+ public function processData($values)
+ {
+ Toolkit_Common::getTableMetaData();
+
+ foreach ($values as $k => $v) {
+ switch ($k) {
+ default :
+ if (preg_match('/^.+_rmv$/', $k)) {
+ unset($values[$k]);
+ }
+ break;
+ }
+ }
+
+ $this->dbh->beginTransaction();
+ if ($this->updateData($values)) {
+ // insert into pending table
+ $this->dbh->commit();
+ } else {
+ $this->dbh->rollBack();
+ }
+
+ $listPage = BASE_URL .
+ "memberdb/index.php?Option=Member&Action=Edit&tab=4";
+ header("Location: $listPage");
+ }
+
+ // }}}
+
+ // {{{ setPending()
+
+ /**
+ * Determines if the member has made any update requests
+ *
+ * Any update requests that are in the member_updates table
+ * will let us know if this member is pending or not.
+ *
+ * @return void
+ * @access protected
+ * @see Toolkit_FormBuilder::setupElements()
+ */
+ public function setPending()
+ {
+ unset ($this->pendingFields);
+ try {
+ $sql = "
+ SELECT DISTINCT label
+ FROM {$this->pendingTable}
+ WHERE member_id = :member_id
+ AND db_table = '{$this->tableName}'";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->execute();
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $this->pendingFields[] = $row['label'];
+ }
+ $this->pending = (count($this->pendingFields)) ? true : false;
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ setupRenderers()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ $renderer =& new HTML_QuickForm_Renderer_Object(true);
+
+ $this->accept($renderer);
+
+ $this->template =& new HTML_Template_Flexy($this->flexyOptions);
+
+ $m = new Toolkit_Members_RecordNavigation($this->config);
+ $m->setupUserNavStructure();
+ // Make the view a copy of the $this object
+ // That way we have access to call functions in
+ // this class from within the template.
+ $this->view = $this;
+ $this->view->form = $renderer->toObject();
+ $this->view->nav = $m->getPageNav();
+ $this->template->compile($this->formTemplate);
+ }
+
+ // }}}
+
+ // {{{ updateData()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param unknown $values Parameter description (if any) ...
+ *
+ * @return unknown Return description (if any) ...
+ * @access public
+ */
+ public function updateData($values)
+ {
+ $id = $GLOBALS['memberAuth']->getAuthData('member_id');
+ $cache = new Cache_Lite(Toolkit_Members::getCacheOptions());
+ $cache->remove("Member_Profile-$id", 'Dynamic');
+
+ if ($this->strictPending) {
+ $this->emailOwner();
+ return $this->createPendingData($values);
+ } else {
+ return parent::insertData($values);
+ }
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/EditMemberOnlyContacts.php b/Toolkit/Members/EditMemberOnlyContacts.php
new file mode 100644
index 0000000..f0df06b
--- /dev/null
+++ b/Toolkit/Members/EditMemberOnlyContacts.php
@@ -0,0 +1,728 @@
+
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: EditMemberOnlyContacts.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Handle associating contacts along with member records
+ *
+ * Controls all aspects of creating and rendering the form used to manipulate
+ * the business contacts. Form is not rendered until the user is added into the Database.
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Members_EditMemberOnlyContacts
+ extends Toolkit_Members_EditMemberOnlyInfo implements Toolkit_Form
+{
+ // {{{ properties
+
+ /**
+ * The table name in the database used to store the data of the files
+ *
+ * @var string
+ * @access public
+ */
+ public $tableName = 'member_contacts';
+
+ /**
+ * The template used to render the form
+ *
+ * @var string
+ * @access protected
+ */
+ protected $formTemplate = 'editContacts.tpl';
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Class constructor
+ *
+ * @param PDO $pdo PHP Data Object to use for DB calls
+ * @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
+ ) {
+ parent::__construct(
+ $pdo,
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+ }
+
+ // }}}
+
+ // {{{ configureDefaults()
+
+ /**
+ * Sets the defaults for elements in the form.
+ *
+ * @return void
+ * @access public
+ */
+ public function configureDefaults()
+ {
+ try {
+ if (isset($_GET['cid'])) {
+ $sql = "
+ select * from {$this->tableName} where id = :cid";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':cid', $_GET['cid'], PDO::PARAM_INT);
+ $stmt->execute();
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+ $defaults['id'] = $row['id'];
+ $defaults['title'] = $row['title'];
+ $defaults['fname'] = $row['fname'];
+ $defaults['lname'] = $row['lname'];
+ $defaults['email'] = $row['email'];
+ $defaults['phone'] = $row['phone'];
+ $defaults['send_mail'] = $row['send_mail'];
+ }
+ $sql = "
+ SELECT *, fname || ' ' || lname AS name,
+ CASE send_mail
+ WHEN 'true' THEN 'Can Mail'
+ ELSE 'No Mail'
+ END AS send_mail
+ FROM {$this->tableName}
+ WHERE member_id = :id
+ ORDER BY id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->execute();
+
+ $i = 0;
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $defaults["cid$i"] = $row['id'];
+ $defaults["title$i"] = $row['title'];
+ $defaults["name$i"] = $row['name'];
+ $defaults["email$i"] = $row['email'];
+ $defaults["phone$i"] = $row['phone'];
+ $defaults["send_mail$i"] = $row['send_mail'];
+ ++$i;
+ }
+ $this->setupDefaults($defaults);
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ configureElements()
+
+ /**
+ * Setup the elements to use on the form.
+ *
+ * @return void
+ * @access public
+ */
+ public function configureElements()
+ {
+ $e = array();
+ $contacts = $this->getMemberContacts();
+ // All Grouped Elements are created here.
+ $submitText = (is_numeric($_GET['cid'])) ? 'Update' : 'Submit';
+
+ // All Elements are created here. This includes group element definitions.
+ $e[] = array(
+ 'type' => 'header',
+ 'req' => false,
+ 'name' => 'fileHdr',
+ 'display' => 'Contacts'
+ );
+ $e[] = array(
+ 'type' => 'hidden',
+ 'req' => false,
+ 'name' => 'id'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'title',
+ 'display' => 'Title',
+ 'opts' => array('class' => 'text')
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'fname',
+ 'display' => 'First Name',
+ 'opts' => array('class' => 'text')
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'lname',
+ 'display' => 'Last Name',
+ 'opts' => array('class' => 'text')
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'email',
+ 'display' => 'Email',
+ 'opts' => array('class' => 'text')
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'phone',
+ 'display' => 'Phone',
+ 'opts' => array('class' => 'text')
+ );
+ $e[] = array(
+ 'type' => 'advcheckbox',
+ 'req' => false,
+ 'name' => 'send_mail',
+ 'display' => 'Receive Mail',
+ 'val' => array(0,
+ 1)
+ );
+ $e[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'submit',
+ 'display' => $submitText,
+ 'opts' => array('class' => 'submit')
+ );
+ if (is_array($contacts)) {
+ foreach ($contacts as $k => $v) {
+ $e[] = array(
+ 'type' => 'header',
+ 'req' => false,
+ 'name' => "fileHdr$k"
+ );
+ $e[] = array(
+ 'type' => 'static',
+ 'req' => false,
+ 'name' => "cid$k"
+ );
+ $e[] = array(
+ 'type' => 'static',
+ 'req' => false,
+ 'name' => "name$k",
+ 'display' => 'Name'
+ );
+ $e[] = array(
+ 'type' => 'static',
+ 'req' => false,
+ 'name' => "title$k"
+ );
+ $e[] = array(
+ 'type' => 'static',
+ 'req' => false,
+ 'name' => "email$k",
+ 'display' => 'Email'
+ );
+ $e[] = array(
+ 'type' => 'static',
+ 'req' => false,
+ 'name' => "phone$k",
+ 'display' => 'Phone'
+ );
+ $e[] = array(
+ 'type' => 'static',
+ 'req' => false,
+ 'name' => "send_mail$k",
+ 'display' => 'Receive Mail'
+ );
+ }
+ }
+
+ $this->setupElements($e);
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Sets up all the rules to be used when the form is validated.
+ *
+ * @return void
+ * @access public
+ */
+ public function configureRules()
+ {
+ // form rules
+ $r = array();
+ $this->registeredRules = array('phone', 'email');
+ $r[] = array(
+ 'element' => 'email',
+ 'message' => 'ERROR: Invalid Email Address!',
+ 'type' => 'email',
+ 'format' => null,
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ /*
+ $r[] = array(
+ 'element' => 'phone',
+ 'message' => 'ERROR: Invalid Phone Number!',
+ 'type' => 'phone',
+ 'format' => null,
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ */
+ $this->setupRules($r);
+ }
+
+ // }}}
+
+ // {{{ getDelUrl()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param object $sec Parameter description (if any) ...
+ *
+ * @return mixed Return description (if any) ...
+ * @access public
+ */
+ public function getDelUrl($sec)
+ {
+ return $_SERVER['REQUEST_URI'] . "&d=t&cid={$sec->elements[0]->html}";
+ }
+
+ // }}}
+ // {{{ getEditUrl()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param object $sec Parameter description (if any) ...
+ *
+ * @return mixed Return description (if any) ...
+ * @access public
+ */
+ public function getEditUrl($sec)
+ {
+ return $_SERVER['REQUEST_URI'] . "&cid={$sec->elements[0]->html}";
+ }
+
+ // }}}
+ // {{{ getImgUrl()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param unknown $type Parameter description (if any) ...
+ *
+ * @return string Return description (if any) ...
+ * @access public
+ */
+ public function getImgUrl($type)
+ {
+ return BASE_URL . "assets/$type";
+ }
+
+ // }}}
+ // {{{ getMailIcon()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param object $sec Parameter description (if any) ...
+ *
+ * @return string Return description (if any) ...
+ * @access public
+ */
+ public function getMailIcon($sec)
+ {
+ $status = $sec->elements[5]->html;
+ $icon = ($status == 'No Mail') ? '-Not-Ok' : '-Ok';
+ return '';
+ }
+
+ // }}}
+ // {{{ getMemberContacts()
+
+ /**
+ * Get all the contacts data uploaded to a member into an array
+ *
+ * @return array member contacts
+ * @access protected
+ */
+ protected function getMemberContacts()
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE member_id = :id
+ ORDER BY id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->execute();
+
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $contacts[] = $row;
+ }
+ return $contacts;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ insertData()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param array $values Parameter description (if any) ...
+ *
+ * @return object Return description (if any) ...
+ * @access public
+ */
+ public function insertData($values)
+ {
+ unset(
+ $values['id'],
+ $values['target'],
+ $values['submit']
+ );
+ $values['member_id'] = $_GET['id'];
+ try {
+ $params = implode(', ', array_keys($values));
+ $bindParams = ':' . implode(', :', array_keys($values));
+ $sql = "
+ INSERT INTO {$this->tableName} ($params)
+ VALUES ($bindParams)";
+ $stmt = $this->dbh->prepare($sql);
+ foreach ($values as $k => $v) {
+ $metaData = $this->tableMetaData[$k];
+ if ($metaData == 'integer') {
+ $dataType = PDO::PARAM_INT;
+ } else if ($metaData == 'boolean') {
+ $dataType = PDO::PARAM_BOOL;
+ } elseif ($metaData == 'double precision') {
+ $dataType = null;
+ } else {
+ $dataType = PDO::PARAM_STR;
+ }
+ $stmt->bindParam(":$k", $values[$k], $dataType);
+ }
+ return $stmt->execute();
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ isEmail()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param unknown $name Parameter description (if any) ...
+ *
+ * @return mixed Return description (if any) ...
+ * @access public
+ */
+ public function isEmail($name)
+ {
+ return (substr($name, 0, 5) == 'email');
+ }
+
+ // }}}
+ // {{{ isForm()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param unknown $sec Parameter description (if any) ...
+ *
+ * @return unknown Return description (if any) ...
+ * @access public
+ */
+ public function isForm($sec)
+ {
+ return !$sec;
+ }
+
+ // }}}
+ // {{{ isName()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param unknown $name Parameter description (if any) ...
+ *
+ * @return mixed Return description (if any) ...
+ * @access public
+ */
+ public function isName($name)
+ {
+ return (substr($name, 0, 4) == 'name');
+ }
+
+ // }}}
+ // {{{ isPhone()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param unknown $name Parameter description (if any) ...
+ *
+ * @return mixed Return description (if any) ...
+ * @access public
+ */
+ public function isPhone($name)
+ {
+ return (substr($name, 0, 5) == 'phone');
+ }
+
+ // }}}
+ // {{{ isTitle()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param unknown $name Parameter description (if any) ...
+ *
+ * @return mixed Return description (if any) ...
+ * @access public
+ */
+ public function isTitle($name)
+ {
+ return (substr($name, 0, 5) == 'title');
+ }
+
+ // }}}
+
+ // {{{ processData()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param array $values Parameter description (if any) ...
+ *
+ * @return void
+ * @access public
+ */
+ public function processData($values)
+ {
+ Toolkit_Common::getTableMetaData();
+ if (empty($values['id'])) {
+ $this->insertData($values);
+ } else {
+ $this->updateData($values);
+ }
+ $listPage = BASE_URL .
+ "memberdb/index.php?Option=Member&Action=Edit&tab=6";
+ header("Location: $listPage");
+ }
+
+ // }}}
+
+ // {{{ removeContact()
+
+ /**
+ * Remove a contact from a member record
+ *
+ * @param integer $cid contact id
+ * @param integer $mid member id
+ *
+ * @return void
+ * @access public
+ */
+ public function removeContact($cid, $mid)
+ {
+ try {
+ $sql = "
+ DELETE FROM {$this->tableName}
+ WHERE id = :cid
+ AND member_id = :mid";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':cid', $cid, PDO::PARAM_INT);
+ $stmt->bindParam(':mid', $mid, PDO::PARAM_INT);
+ $stmt->execute();
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ setupRenderers()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ $renderer =& new HTML_QuickForm_Renderer_Object(true);
+
+ $this->accept($renderer);
+
+ $this->template =& new HTML_Template_Flexy($this->flexyOptions);
+
+ $m = new Toolkit_Members_RecordNavigation($this->config);
+ $m->setupUserNavStructure();
+ // Make the view a copy of the $this object
+ // That way we have access to call functions in
+ // this class from within the template.
+ $this->view = $this;
+ $this->view->form = $renderer->toObject();
+ $this->view->nav = $m->getPageNav();
+ $this->template->compile($this->formTemplate);
+ }
+
+ // }}}
+ // {{{ show()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @return void
+ * @access public
+ */
+ public function show()
+ {
+ if (isset($_GET['d'])) {
+ $this->removeContact($_GET['cid']);
+ $target = BASE_URL .
+ "memberdb/index.php?Option=Member&Action=Edit&tab=6";
+ header("Location: $target");
+ }
+ Toolkit_Common::show();
+ }
+
+ // }}}
+
+ // {{{ updateData()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param array $values Parameter description (if any) ...
+ *
+ * @return object Return description (if any) ...
+ * @access public
+ */
+ public function updateData($values)
+ {
+ if (array_key_exists('delete', $values)) {
+ $this->deleteFile($values);
+ }
+
+ unset(
+ $values['target'],
+ $values['submit']
+ );
+
+ try {
+ $params = array_keys($values);
+ $length = count($params);
+ for ($i = 0; $i < $length; ++$i) {
+ $bindParams .= "{$params[$i]} = :{$params[$i]}";
+ if ($i < ($length - 1)) {
+ $bindParams .= ', ';
+ }
+ }
+ $sql = "
+ UPDATE {$this->tableName}
+ SET $bindParams
+ WHERE id = :id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $pid, PDO::PARAM_INT);
+ foreach ($values as $k => $v) {
+ $metaData = $this->tableMetaData[$k];
+ if ($metaData == 'integer') {
+ $dataType = PDO::PARAM_INT;
+ } else if ($metaData == 'boolean') {
+ $dataType = PDO::PARAM_BOOL;
+ } else {
+ $dataType = PDO::PARAM_STR;
+ }
+ $stmt->bindParam(":$k", $values[$k], $dataType);
+ }
+ return $stmt->execute();
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/EditMemberOnlyFile.php b/Toolkit/Members/EditMemberOnlyFile.php
new file mode 100644
index 0000000..8376510
--- /dev/null
+++ b/Toolkit/Members/EditMemberOnlyFile.php
@@ -0,0 +1,424 @@
+
+ * @author Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: EditMemberOnlyFile.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Controls for uploading / editing files for a business record
+ *
+ * Controls all aspects of creating and rendering the form used to manipulate
+ * the business files. Form is not rendered until the user is added into the
+ * Database.
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Steve Sutton
+ * @author Jamie Kahgee
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit_Members_EditMemberInfo, Toolkit_Members_EditMemberFile
+ */
+class Toolkit_Members_EditMemberOnlyFile
+ extends Toolkit_Members_EditMemberFile implements Toolkit_Form
+{
+ // {{{ __construct()
+
+ /**
+ * Class constructor
+ *
+ * @param PDO $pdo PHP Data Object to use for DB calls
+ * @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
+ ) {
+ parent::__construct(
+ $pdo,
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+ $this->setPending();
+ }
+
+ // }}}
+
+ // {{{ configureDefaults()
+
+ /**
+ * Sets the defaults for elements in the form
+ *
+ * Handles setting the normal defaults by way of the parents function.
+ * Then overrides any caption updates by grabbing the latest update
+ * submitted for any caption in the updates table and sets those as
+ * the defaults instead.
+ *
+ * @return void
+ * @access public
+ */
+ public function configureDefaults()
+ {
+ parent::configureDefaults();
+ try {
+ // Get all the latest file name updates for the files
+ // EXCEPT any file that has an update of [0].
+ // zero denotes a newly uploaded file and doesn't yet have
+ // a caption.
+ $sql = "
+ SELECT 'mu.update', mf.id
+ FROM {$this->pendingTable} mu, {$this->tableName} mf
+ WHERE mu.id in (
+ SELECT max(id)
+ FROM {$this->pendingTable}
+ WHERE db_table = '{$this->tableName}'
+ AND member_id = :member_id
+ GROUP BY foreign_key)
+ AND mu.field = 'file_name'
+ AND mu.foreign_key = mf.id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->execute();
+
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $fields[] = $row;
+ }
+
+ if (!empty($fields)) {
+ $sql = "
+ SELECT count(*)
+ FROM {$this->tableName}
+ WHERE id < :id
+ AND member_id = :member_id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $_GET['id'], PDO::PARAM_INT);
+ foreach ($fields as &$f) {
+ $stmt->bindParam(':id', $f['id'], PDO::PARAM_INT);
+ $stmt->execute();
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+ $defaults["file_name{$row['count']}"] = $f['update'];
+ }
+ $this->setupDefaults($defaults);
+ }
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ insertData()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param array $values Parameter description (if any) ...
+ *
+ * @return mixed Return description (if any) ...
+ * @access public
+ */
+ public function insertData($values)
+ {
+ if ($this->strictPending) {
+ try {
+ $this->dbh->beginTransaction();
+ // Insert the file the normal way, w/ pending being true.
+ parent::insertData($values, $pending = true);
+
+ // Get the last file inserted.
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE pending = true
+ AND member_id = :member_id
+ ORDER BY id DESC";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->execute();
+ $file = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ // Insert the file into the updates table for approval.
+ $fname = empty($values['file_name']) ?
+ $values['file_rmv']['name'] :
+ $values['file_name'];
+ $imgTag = '';
+ $label = '
');
+
+ $menu->render($renderer);
+ return $renderer->toHtml();
+ }
+
+ // }}}
+
+ // {{{ setupAdminNavStructure()
+
+ /**
+ * Sets up a multi dimensional array used for the subnav structure
+ *
+ * @return mixed false on sql error. otherwise void
+ * @access public
+ */
+ public function setupAdminNavStructure()
+ {
+ // get reference to [listing type] section of config file
+ $config =& $this->config->getItem('section', 'listing type');
+ // get coupon
+ $singularDirective =& $config->getItem('directive', 'singular');
+ $singularType = $singularDirective->getContent();
+ $pluralDirective =& $config->getItem('directive', 'plural');
+ $pluralType = $pluralDirective->getContent();
+
+ // Default URI parameters that will get us back to the
+ // page were we can edit member data.
+ $params = "cat=2&subCat=2";
+
+ // If we are editing an existing member, then we need to
+ // add their id into the URI so we know who we are editing
+ if (is_numeric($_GET['id'])) {
+ $params .= "&id={$_GET['id']}";
+ }
+
+ // We always show the member info tab.
+ // whether we are adding a member or editing a member
+ $nav = array(
+ 1 => array(
+ 'Title' => "$singularType Info",
+ 'url' => "/members.php?$params",
+ 'desc' => "View and edit $singularType in the database",
+ )
+ );
+ if (is_numeric($_GET['id'])) {
+ $nav[2] = array(
+ 'Title' => 'Photos',
+ 'url' => "/members.php?$params",
+ 'desc' => "View and edit $pluralType in the database",
+ );
+ $nav[3] = array(
+ 'Title' => 'Packages',
+ 'url' => "/members.php?$params",
+ 'desc' => "View and edit $singularType categories",
+ );
+ $nav[4] = array(
+ 'Title' => 'Amenities',
+ 'url' => "/members.php?$params",
+ 'desc' => "View and edit $singularType amenities",
+ );
+ $nav[5] = array(
+ 'Title' => 'Files',
+ 'url' => "/members.php?$params",
+ 'desc' => "View and edit $singularType regions",
+ );
+ $nav[6] = array(
+ 'Title' => 'Contacts',
+ 'url' => "/members.php?$params",
+ 'desc' => "View and edit $singularType cities",
+ );
+ }
+
+ // make full URI's and attach which tab we are working with
+ foreach ($nav as $i => &$j) {
+ $j['url'] = BASE_URL . 'admin' . $j['url'] . "&tab=$i";
+ }
+
+ $this->navStructure = $nav;
+ }
+
+ // }}}
+ // {{{ setupUserNavSructure()
+
+ /**
+ * Sets up a multi dimensional array used for the subnav structure
+ *
+ * @return mixed false on sql error. otherwise void
+ * @access public
+ */
+ public function setupUserNavStructure()
+ {
+ // get reference to [listing type] section of config file
+ $config =& $this->config->getItem('section', 'listing type');
+ // get coupon
+ $singularDirective =& $config->getItem('directive', 'singular');
+ $singularType = $singularDirective->getContent();
+ $pluralDirective =& $config->getItem('directive', 'plural');
+ $pluralType = $pluralDirective->getContent();
+
+ $params = "Option=Member&Action=Edit";
+ $nav = array(
+ 1 => array(
+ 'Title' => "$singularType Info",
+ 'url' => "/index.php?$params",
+ 'desc' => "View and edit $singularType in the database",
+ ),
+ 2 => array(
+ 'Title' => 'Photos',
+ 'url' => "/index.php?$params",
+ 'desc' => "View and edit $pluralType in the database",
+ ),
+ 3 => array(
+ 'Title' => 'Packages',
+ 'url' => "/index.php?$params",
+ 'desc' => "View and edit $singularType categories",
+ ),
+ 4 => array(
+ 'Title' => 'Amenities',
+ 'url' => "/index.php?$params",
+ 'desc' => "View and edit $singularType amenities",
+ ),
+ 5 => array(
+ 'Title' => 'Files',
+ 'url' => "/index.php?$params",
+ 'desc' => "View and edit $singularType regions",
+ ),
+ 6 => array(
+ 'Title' => 'Contacts',
+ 'url' => "/index.php?$params",
+ 'desc' => "View and edit $singularType cities",
+ ),
+ );
+
+ // make full URI's and attach which tab we are working with
+ foreach ($nav as $i => &$j) {
+ $j['url'] = BASE_URL . 'memberdb' . $j['url'] . "&tab=$i";
+ }
+
+ $this->navStructure = $nav;
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/SearchList.php b/Toolkit/Members/SearchList.php
new file mode 100644
index 0000000..bec68dd
--- /dev/null
+++ b/Toolkit/Members/SearchList.php
@@ -0,0 +1,728 @@
+
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @release CVS: $Id: SearchList.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+require_once 'FlexyDataGridBuilder.php';
+require_once 'Members/UserSearchForm.php';
+require_once 'Members/Exposure.php';
+require_once 'Common.php';
+require_once 'HTML/QuickForm/Renderer/Object.php';
+
+/**
+ * Datagrid of search results of member db
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Members_SearchList extends Toolkit_FlexyDataGridBuilder
+{
+ // {{{ properties
+
+ /**
+ * Description for protected
+ * @var string
+ * @access protected
+ */
+ protected $tableName = 'member';
+
+ /**
+ * Description for protected
+ * @var array
+ * @access protected
+ */
+ protected $queryParams = array();
+
+ /**
+ * Description for protected
+ * @var unknown
+ * @access protected
+ */
+ protected $showSearchBox;
+
+ /**
+ * Description for protected
+ * @var string
+ * @access protected
+ */
+ protected $template = 'membersList.tpl';
+
+ /**
+ * Whether subcats should be included in the search results
+ *
+ * If this is turned on, the subcategories beneath all categories assigned
+ * to the page will be included in the search results.
+ *
+ * Example Category Tree:
+ *
+ * Parent
+ * |_ Child
+ * | |_ GrandChild
+ * |
+ * |_ Sibling
+ *
+ * If set to true and only "Parent" is assigned to a page from the toolbox,
+ * then members with all categories (parent, child, grandchild, sibling) will
+ * be included in the search results.
+ *
+ * If set to false and only Child is assigned to a page, then only members
+ * that have the category "Child" assigned to them will be included in the
+ * search Results.
+ *
+ * @var boolean
+ * @access protected
+ */
+ protected $includeSubCats = true;
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Class constructor
+ *
+ * define where templates for the data grid are at, then call the parent constructor which will handle
+ * finishing the settings for the datagrid.
+ *
+ * After all settings are finished you can call the toHTML() function on this object and the datagrid
+ * will be rendered and returned as a string. Optionally you could call show() and the datagrid would
+ * be rendered and output immediatley to the screen.
+ *
+ * @param PDO $pdo PHP Data Object to use for DB calls
+ * @param string $limit The number of records to display per page.
+ * @param int $page The current page viewed.
+ * In most cases, this is useless.
+ * Note: if you specify this, the "page" GET
+ * variable will be ignored.
+ * @param string $rendererType The type of renderer to use.
+ * You may prefer to use the $type argument
+ * of {@link render}, {@link fill} or
+ * {@link getOutput}
+ * @param boolean $showSearchBox If we should allow searching for members
+ * @param array $sections specific members we should show
+ *
+ * @return void
+ * @access public
+ */
+ public function __construct(
+ PDO $pdo,
+ $limit = null,
+ $page = null,
+ $rendererType = null,
+ $showSearchBox = true,
+ array $sections = null
+ ) {
+ $this->showSearchBox = $showSearchBox;
+ $this->pagerOptions['containerClass'] = 'pages';
+ parent::__construct($pdo, $limit, $page, $rendererType);
+ }
+
+ // }}}
+
+ // {{{ city()
+
+ /**
+ * Returns the city for a member.
+ *
+ * If this memberdb is using controlled cities then we need to extract
+ * the city name via the city_id
+ *
+ * @param array $data tuple record from db
+ *
+ * @return string City name for the record
+ * @access public
+ */
+ public function city($data)
+ {
+ // get reference to [conf] section of config file
+ $config =& $this->config->getItem('section', 'conf');
+ $ctrlCtyD =& $config->getItem('directive', 'controlledCities');
+ if ($ctrlCtyD->getContent()) {
+ return $data['record']['city_name'];
+ } else {
+ return $data['record']['city'];
+ }
+ }
+
+ // }}}
+ // {{{ configureColumns()
+
+ /**
+ * Configures the columns that will be used in our datagrid renderer.
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureColumns()
+ {
+ $logo =& new Structures_DataGrid_Column('Logo',
+ 'logo',
+ 'logo',
+ null,
+ null,
+ array(&$this, 'logo'));
+ $this->addColumn($logo);
+
+ $name =& new Structures_DataGrid_Column('Member Name',
+ 'member_name',
+ 'member_name');
+ $this->addColumn($name);
+
+ $street =& new Structures_DataGrid_Column('Street',
+ 'street',
+ 'street');
+ $this->addColumn($street);
+
+ $city =& new Structures_DataGrid_Column('City',
+ 'city',
+ 'city',
+ null,
+ null,
+ array(&$this, 'city'));
+ $this->addColumn($city);
+
+ $state =& new Structures_DataGrid_Column('State',
+ 'state',
+ 'state');
+ $this->addColumn($state);
+
+ $stateAbbr =& new Structures_DataGrid_Column('State Abbr',
+ 'state_abbr',
+ 'state_abbr');
+ $this->addColumn($stateAbbr);
+
+ $zip =& new Structures_DataGrid_Column('Zip',
+ 'zip',
+ 'zip');
+ $this->addColumn($zip);
+
+ $phone =& new Structures_DataGrid_Column('Phone',
+ 'phone',
+ 'phone',
+ null,
+ null,
+ array(&$this, 'phone'));
+ $this->addColumn($phone);
+
+ $url =& new Structures_DataGrid_Column('URL',
+ 'url',
+ 'url',
+ null,
+ null,
+ array(&$this, 'url'));
+ $this->addColumn($url);
+
+ $reservationId =& new Structures_DataGrid_Column('Reservation Id',
+ 'reservation_id',
+ 'reservation_id');
+ $this->addColumn($reservationId);
+
+ $numRooms =& new Structures_DataGrid_Column('Number of Rooms',
+ 'num_rooms',
+ 'num_rooms');
+ $this->addColumn($numRooms);
+
+ $yearRound =& new Structures_DataGrid_Column('Year Round',
+ 'year_round',
+ 'year_round',
+ null,
+ null,
+ array(&$this, 'yearRound'));
+ $this->addColumn($yearRound);
+
+ $hasHotelInfo =& new Structures_DataGrid_Column(null,
+ 'has_hotel_info',
+ 'has_hotel_info',
+ null,
+ null,
+ array(&$this, 'hasHotelInfo'));
+ $this->addColumn($hasHotelInfo);
+
+ if (defined("MEMBER_SESSION_LIST") && MEMBER_SESSION_LIST) {
+ $link =& new Structures_DataGrid_Column('URL',
+ 'plink',
+ 'plink',
+ null,
+ null,
+ array(&$this, 'listUrl'));
+ $this->addColumn($link);
+ }
+
+ $link =& new Structures_DataGrid_Column('addToLink',
+ 'addToLink',
+ 'addToLink',
+ null,
+ null,
+ array(&$this, 'inList'));
+ $this->addColumn($link);
+ }
+
+ // }}}
+
+ // {{{ getAlphaList()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @return array Return description (if any) ...
+ * @access protected
+ */
+ protected function getAlphaList()
+ {
+ $pattern = "/ (\s*?AND\s*?)?upper\(substr\(m.member_name, 1, 1\)\) = upper\('.'\)/i";
+ $replacement = '';
+ $sql = preg_replace($pattern, $replacement, $this->sql);
+ try {
+ $letters = array();
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->execute();
+
+ $stmt->bindColumn('member_name', $name);
+
+ while ($row = $stmt->fetch()) {
+ $letters[] = strtoupper($name{0});
+ }
+
+ $letters = array_unique($letters);
+ sort($letters);
+
+ // We only need to show the links of alphabet if we have more than
+ // one letter to display.
+ if (count($letters) > 1) {
+ foreach ($_GET as $k => $v) {
+ if ($k != 'alpha') {
+ if (is_array($v)) {
+ foreach ($v as $i => $j) {
+ $queryString .= $k . '[' . $i . ']=' . $j . '&';
+ }
+ } else {
+ $queryString .= "$k=$v&";
+ }
+ }
+ }
+ $links['All']['url'] = BASE_URL . "index.php?{$queryString}";
+ $links['All']['class'] = empty($_GET['alpha']) ? 'curr' : null;
+ foreach ($letters as $v) {
+ $links[$v]['url'] = BASE_URL . "index.php?{$queryString}alpha=$v";
+ if ($_GET['alpha'] == $v) {
+ $links[$v]['class'] = 'curr';
+ }
+ }
+ return $links;
+ }
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ _getMemberCategoriesForPage()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @return mixed Return description (if any) ...
+ * @access private
+ */
+ private function _getMemberCategoriesForPage()
+ {
+ try {
+ $memberCategories = array();
+ $sql = "
+ SELECT memb_type
+ FROM bus_cat_member
+ WHERE catid = :catid";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':catid', $_GET['catid'], PDO::PARAM_INT);
+ $stmt->execute();
+ $stmt->bindColumn('memb_type', $category);
+
+ while ($row = $stmt->fetch()) {
+ $memberCategories[] = $category;
+ }
+
+ // If we should include all the sub categories beneath a category.
+ if ($this->includeSubCats) {
+ // For each of the categories assigned to the page,
+ // we need to get all sub-categories. This way the user
+ // can assign a top level category as a balloon to cover all the
+ // subcategories w/out individually assigning them as well.
+ foreach ($memberCategories as $v) {
+ $catTree = Toolkit_Common::getHierarchicalTreeStructure(
+ 'category',
+ 'category_id',
+ 'parent_id',
+ 'pos',
+ $v
+ );
+
+ foreach ($catTree as $i => $j) {
+ $memberCategories[] = $i;
+ }
+ }
+ }
+
+ return empty($memberCategories) ? false : $memberCategories;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ hasHotelInfo()
+
+ /**
+ * Determines if the record has any available hotel info to display
+ *
+ * @param array $data record data
+ *
+ * @return boolean true if any data to display, otherwise false
+ * @access public
+ */
+ public function hasHotelInfo($data)
+ {
+ extract($data['record']);
+ return !(empty($reservation_id) && empty($num_rooms) && empty($year_round));
+ }
+
+ // }}}
+
+ // {{{ inList()
+
+ /**
+ * Returns the bool for a member in session (list)
+ *
+ * Used when configuring the columns for the data grid. This
+ * function returns true or false if the member is in not session
+ * then true
+ *
+ * @param array $data tuple record from db
+ *
+ * @return boolean true if member is not in $_SESSION['wish_list']
+ * @access public
+ */
+ public function inList($data)
+ {
+ return !($_SESSION['wish_list'][$data['record']['member_id']]);
+ }
+
+ // }}}
+
+ // {{{ listUrl()
+
+ /**
+ * Returns the url for a member.
+ *
+ * Used when configuring the columns for the data grid. This
+ * function generates the url to get to the member detail page
+ *
+ * @param array $data tuple record from db
+ *
+ * @access Public
+ * @version Release: @package_version@
+ * @return url for the add to or remove from $_SESSION['wish_list']
+ */
+ public function listUrl($data)
+ {
+ if (defined("MEMBER_SESSION_LIST") && MEMBER_SESSION_LIST) {
+ $url = BASE_URL."Toolkit/Members/TripPlanner/wish-list.php?catid={$_GET['catid']}&member_id={$data['record']['member_id']}";
+ $url .= ($_REQUEST['search']) ? "&search=" . $_REQUEST['search'] :'';
+ $url .= ($_REQUEST['member_name']) ? "&member_name=" . urlencode($_REQUEST['member_name']) :'';
+ $url .= ($_REQUEST['category_id']) ? "&category_id=" . $_REQUEST['category_id'] :'';
+ $url .= ($_REQUEST['sub_category_id']) ? "&sub_category_id=" . $_REQUEST['sub_category_id'] :'';
+ } else {
+ $url = false;
+ }
+ return $url;
+ }
+
+ // }}}
+ // {{{ logo()
+
+ /**
+ * Returns the logo for a member.
+ *
+ * @param array $data tuple record from db
+ *
+ * @return false when empty, otherwise logo path for member
+ * @access
+ */
+ public function logo($data)
+ {
+ extract($data['record']);
+ return empty($logo) ? false : MEMBER_PHOTOS . $logo;
+ }
+
+ // }}}
+
+ // {{{ phone()
+
+ /**
+ * Returns the phone # for a member.
+ *
+ * Used when configuring the columns for the data grid. This
+ * function generates the phone for the member
+ *
+ * @param array $data tuple record from db
+ *
+ * @return mixed false when empty, member phone number if not empty
+ * @access public
+ */
+ public function phone($data)
+ {
+ extract($data['record']);
+ return empty($phone) ? false : $phone;
+ }
+
+ // }}}
+
+ // {{{ setConfig()
+
+ /**
+ * Sets the query to use to fetch the datagrid results
+ *
+ * @param Config_Container $c Configuration object
+ *
+ * @return void
+ * @access public
+ */
+ public function setConfig(Config_Container $c)
+ {
+ $this->config = $c;
+ }
+
+ // }}}
+ // {{{ setControlObject()
+
+ /**
+ * These are the objects that will be inserted into the template.
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setControlObject()
+ {
+ $this->ctrlObj['base_url'] = BASE_URL;
+ $this->ctrlObj['letters'] = $this->getAlphaList();
+
+ if (isset($_GET['search']) && $this->showSearchBox) {
+ $action = BASE_URL . "index.php?{$_SERVER['QUERY_STRING']}";
+ $form = new Toolkit_Members_UserSearchForm($this->dbh,
+ 'SearchForm',
+ 'get',
+ $action,
+ null,
+ null,
+ true);
+ $res = $form->setCatId($_GET['catid']);
+ if (PEAR::isError($res)) {
+ return Toolkit_Common::handleError($res);
+ } else {
+ $form->setPageMemberCategories();
+ $form->configureForm($this->config);
+ $this->ctrlObj['member_search_form'] = $form->toHtml();
+ }
+ }
+ }
+
+ // }}}
+ // {{{ setQuery()
+
+ /**
+ * Sets the query to use to fetch the datagrid results
+ *
+ * @return void
+ * @access public
+ */
+ public function setQuery()
+ {
+ $sql = "
+ SELECT m.*, c.city_name, s.state_name AS state, s.state_abb
+ AS state_abbr, ma.reservation_id, ma.num_rooms,
+ ma.year_round
+ FROM {$this->tableName} m
+ NATURAL LEFT JOIN member_accommodations ma
+ JOIN state s ON m.state_id = s.state_id
+ JOIN city c ON m.city_id = c.city_id";
+
+ $this->queryParams = array("new_member != '1'", "active = '1'");
+
+ // Limit to members whose first letter starts with the letter
+ // a user clicked in the sort alphabetically list.
+ if (ctype_alpha($_GET['alpha'])) {
+ $this->queryParams[] = "upper(substr(m.member_name, 1, 1)) = upper('{$_GET['alpha']}')";
+ }
+
+ // Limit to members whose name contains the string a user
+ // entered into the member name box.
+ if (!empty($_GET['member_name'])) {
+ $this->queryParams[] = "member_name ilike '%{$_GET['member_name']}%'";
+ }
+
+ // Using controlled cities and a search was performed on a city
+ // get reference to [conf] section of config file
+ $config =& $this->config->getItem('section', 'conf');
+ $ctrlCtyD =& $config->getItem('directive', 'controlledCities');
+ if ($ctrlCtyD->getContent()) {
+ if (ctype_digit($_GET['city_id'])) {
+ $this->queryParams[] = "c.city_id = {$_GET['city_id']}";
+ }
+ }
+
+ // Limit to members who have the category assigned to them
+ // that a user selected from the member type box.
+ if (ctype_digit($_GET['sub_category_id'])) {
+ $this->queryParams[] = "
+ m.member_id IN (
+ SELECT member_id
+ FROM member_category
+ WHERE category_id = {$_GET['sub_category_id']})";
+ } else if (ctype_digit($_GET['category_id'])) {
+ unset($subCats);
+ if ($this->includeSubCats) {
+ // Members who are assigned specifically to this category
+ // OR
+ // Members who have a category assigned to them that is a child
+ // of the parent category.
+ $catTree = Toolkit_Common::getHierarchicalTreeStructure(
+ 'category',
+ 'category_id',
+ 'parent_id',
+ 'pos',
+ $_GET['category_id']
+ );
+
+ if (!empty($catTree)) {
+ $subCats = "
+ OR category_id IN (".implode(', ', array_keys($catTree)).")";
+ }
+ }
+ $this->queryParams[] = "
+ m.member_id IN (
+ SELECT member_id
+ FROM member_category
+ WHERE category_id = {$_GET['category_id']}
+ $subCats)";
+ } elseif ($categories = $this->_getMemberCategoriesForPage()) {
+ $this->queryParams[] = '
+ m.member_id in (
+ SELECT member_id
+ FROM member_category
+ WHERE category_id in ('.implode(', ', $categories).'))';
+ }
+
+ // Limit to members who have the amenities that a user
+ // checked off.
+ if (!empty($_GET['amenities'])) {
+ if (isset($_GET['search_all_amenity'])) {
+ // Member must have ALL of the selected amenities.
+ foreach ($_GET['amenities'] as $k => $v) {
+ if (ctype_digit($k)) {
+ $innerSql[] = "
+ SELECT member_id
+ FROM member_amenity
+ WHERE amenity_id = $k";
+ }
+ }
+
+ $innerSql = implode(' INTERSECT ', $innerSql);
+ $innerSql = "m.member_id in ($innerSql)";
+
+ $this->queryParams[] = $innerSql;
+ } else {
+ // Member can have ANY of the selected amenities
+ $this->queryParams[] = "
+ member_id in (
+ SELECT member_id
+ FROM member_amenity
+ WHERE amenity_id in(".implode(', ', array_keys($_GET['amenities']))."))";
+ }
+ }
+
+ if (!is_null($sections)) {
+ foreach ($sections as $v) {
+ switch ($v) {
+ case 'packages' :
+ $this->queryParams[] = "
+ member_id IN (
+ SELECT member_id
+ FROM member_packages)";
+ break;
+
+ default :
+ break;
+ }
+ }
+ }
+
+ if (!empty($this->queryParams)) {
+ $sql .= ' WHERE ' . implode(' AND ', $this->queryParams);
+ }
+
+ parent::setQuery($sql);
+ }
+
+ // }}}
+
+ // {{{ url()
+
+ /**
+ * Returns the url for a member.
+ *
+ * Used when configuring the columns for the data grid. This
+ * function generates the url to get to the member detail page
+ *
+ * @param array $data tuple record from db
+ *
+ * @return string uri for exposure record
+ * @access public
+ */
+ public function url($data)
+ {
+ $exposure = new Toolkit_Members_Exposure($data['record']['member_id'], 'list');
+ return "index.php?catid={$_GET['catid']}&member_id={$data['record']['member_id']}";
+ }
+
+ // }}}
+
+ // {{{ yearRound()
+
+ /**
+ * Returns the year round for a member w/ accommodations.
+ *
+ * Used when configuring the columns for the data grid. This
+ * function generates the year round for the member detail page
+ *
+ * @param array $data tuple record from db
+ *
+ * @return string if the accommodations is offered year round
+ * @access public
+ */
+ public function yearRound($data)
+ {
+ return ($data['record']['year_round'] == 't') ? 'Yes' : 'No';
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/TripPlanner/Sessions.php b/Toolkit/Members/TripPlanner/Sessions.php
new file mode 100644
index 0000000..99fd319
--- /dev/null
+++ b/Toolkit/Members/TripPlanner/Sessions.php
@@ -0,0 +1,290 @@
+
+ * @copyright 2009 Gaslight Media
+ * @license Gaslight Media
+ * @version CVS: $Id: Sessions.php,v 1.2 2009/12/15 20:18:15 jamie Exp $
+ * @link <>
+ */
+
+/**
+ * Toolkit_Members_TripPlanner_Sessions
+ *
+ * Trying to place all the code for the storing of the member list to session
+ * into one place
+ * Takes the $_SESSION['wish_list'] used for the trip planner and
+ * add or removes members and their page id to the session
+ * if they're logged in with trip planner then they'll get everything saved to the
+ * database table member_session
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Steve Sutton
+ * @copyright 2009 Gaslight Media
+ * @license Gaslight Media
+ * @version Release: @package_version@
+ * @link <>
+ */
+class Toolkit_Members_TripPlanner_Sessions
+{
+ // {{{ Properties
+ /**
+ * Global PDO
+ * @var object
+ * @access protected
+ */
+ public $dbh;
+
+ /**
+ * Auth object
+ * @var object
+ * @access protected
+ */
+ protected $auth;
+
+ /**
+ * $_SESSION['wish_list']
+ * @var array
+ * @access protected
+ */
+ protected $session;
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Set the Auth object ad Global PDO
+ *
+ * @param integer $pdo Global pdo
+ * @param integer $Auth current Auth object used for valid session
+ *
+ * @return void
+ * @access public
+ */
+ function __construct($pdo, Auth $Auth)
+ {
+ $this->dbh =& $pdo;
+ $this->auth =& $Auth;
+ $this->session =& $_SESSION['wish_list'];
+ }
+
+ // }}}
+ // {{{ addRecord()
+
+ /**
+ * Add the record into session storing the page it was added on.
+ * page shold always have the catid.
+ * If the user is logged in then store it in database with contact_id
+ *
+ * @param unknown $memberId member_id of record
+ * @param unknown $catId page catid
+ *
+ * @return void
+ * @access public
+ */
+ function addRecord($memberId, $catId)
+ {
+ // add to the session the member record
+ $this->session[$memberId] = array(
+ 'catid' => $catId
+ );
+ if ($this->isLoggedIn()) {
+ $cData = $this->auth->getAuthData();
+ try {
+ $sql = "
+ INSERT INTO member_session
+ (contact_id, member_id, catid)
+ VALUES
+ (:contact_id, :member_id, :catid)";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(":member_id", $memberId, PDO::PARAM_INT);
+ $stmt->bindParam(":contact_id", $cData['id'], PDO::PARAM_INT);
+ $stmt->bindParam(":catid", $catId, PDO::PARAM_INT);
+ $stmt->execute();
+ } catch(PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+ }
+
+ // }}}
+ // {{{ dumpList()
+
+ /**
+ * Dump the session for the list and
+ * if they are logged in then remove their list in the
+ * database.
+ *
+ * @return void
+ * @access public
+ */
+ function dumpList()
+ {
+ if ($this->isLoggedIn()) {
+ $cData = $this->auth->getAuthData();
+ $sql = "
+ DELETE
+ FROM member_session
+ WHERE contact_id = :contact_id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(":contact_id", $cData['id'], PDO::PARAM_INT);
+ $stmt->execute();
+ }
+ unset($this->session);
+ unset($_SESSION['wish_list']);
+ session_unregister('wish_list');
+ }
+
+ // }}}
+ // {{{ isLoggedIn()
+
+ /**
+ * Check the Auth object function checkAuth to see if the user has a valid
+ * login session. If so then return true. If not then return false.
+ *
+ * @return boolean true valid login false invalid login
+ * @access public
+ */
+ function isLoggedIn()
+ {
+ if ($this->auth->checkAuth()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ // }}}
+ // {{{ removeRecord()
+
+ /**
+ * Remove the record from the session. If the user is logged in then
+ * also remove the data from the database.
+ *
+ * @param unknown $memberId member id for record
+ *
+ * @return void
+ * @access public
+ */
+ function removeRecord($memberId)
+ {
+ unset($this->session[$memberId]);
+ if ($this->isLoggedIn()) {
+ $cData = $this->auth->getAuthData();
+ //die('
'.print_r($cData, true).'
');
+ try {
+ $sql = "
+ DELETE FROM member_session
+ WHERE member_id = :member_id
+ AND contact_id = :contact_id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(":member_id", $memberId, PDO::PARAM_INT);
+ $stmt->bindParam(":contact_id", $cData['id'], PDO::PARAM_INT);
+ $stmt->execute();
+ } catch(PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+ }
+
+ // }}}
+ // {{{ retrieveList()
+
+ /**
+ * Retreive the list form the database storage and repopulate the accounts data
+ * to the session var $this->session = $_SESSION['wish_list']
+ *
+ * @return void
+ * @access public
+ */
+ function retrieveList()
+ {
+ if ($this->isLoggedIn()) {
+ $cData = $this->auth->getAuthData();
+ try {
+ $sql = "
+ SELECT *
+ FROM member_session
+ WHERE contact_id = :contact_id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(":contact_id", $cData['id'], PDO::PARAM_INT);
+ $stmt->execute();
+ while ($row = $stmt->fetch()) {
+ // don't dupe the list
+ if (!$this->session[$row['member_id']]) {
+ $this->session[$row['member_id']] = array(
+ 'catid' => $row['catid']
+ );
+ }
+ }
+ } catch(PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+ }
+
+ // }}}
+ // {{{ saveList()
+
+ /**
+ * Save the list for the user. This is called on the login page after the
+ * session is repopulated out from database. No worries about dupes here.
+ * this function checks for existing records then won't reinsert.
+ *
+ * @param int $contactId the id from contact table for lookup
+ *
+ * @return void
+ * @access public
+ */
+ function saveList($contactId = null)
+ {
+ if ($this->isLoggedIn() && is_array($this->session)) {
+ if (isset($contactId) && is_numeric($contactId)) {
+ $cData['id'] = $contactId;
+ } else {
+ $cData = $this->auth->getAuthData();
+ }
+ $sql = "
+ SELECT member_id
+ FROM member_session
+ WHERE contact_id = :contact_id";
+ try {
+ $getDat = $this->dbh->prepare($sql);
+ $getDat->bindParam(":contact_id", $cData['id'], PDO::PARAM_INT);
+ $getDat->execute();
+ while ($row = $getDat->fetch()) {
+ $mStoreSess[$row['member_id']] = $row['member_id'];
+ }
+ } catch(PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ foreach ($this->session as $memberId => $sData) {
+ if (!$mStoreSess[$memberId]) {
+ try {
+ $sql = "
+ INSERT INTO member_session
+ (contact_id, member_id, catid)
+ VALUES
+ (:contact_id, :member_id, :catid)";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(":member_id", $memberId, PDO::PARAM_INT);
+ $stmt->bindParam(":contact_id", $cData['id'], PDO::PARAM_INT);
+ $stmt->bindParam(":catid", $sData['catid'], PDO::PARAM_INT);
+ $stmt->execute();
+ } catch(PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+ }
+ }
+ }
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/TripPlanner/TripAuth.php b/Toolkit/Members/TripPlanner/TripAuth.php
new file mode 100644
index 0000000..4a21ad5
--- /dev/null
+++ b/Toolkit/Members/TripPlanner/TripAuth.php
@@ -0,0 +1,788 @@
+
+ * @copyright 2009 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: TripAuth.php,v 1.2 2009/12/15 20:18:16 jamie Exp $
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit_Members_Auth-LoginForm, Toolkit_Members_Auth-PasswordForm
+ */
+
+require_once 'Auth.php';
+
+/**
+ * Methods for the memberdb authentication system
+ *
+ * Handles Cookie and session generation, id challenges and security for
+ * the memberdb application
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Steve Sutton
+ * @copyright 2009 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit_Members_Auth-LoginForm, Toolkit_Members_Auth-PasswordForm
+ */
+class Toolkit_Members_TripPlanner_TripAuth extends Auth
+{
+ // {{{ properties
+
+ /**
+ * Maximum idle time
+ *
+ * If more seconds pass before a new page request, then the user
+ * will have to re-authenticate back into the application.
+ * 1800 = 30 min
+ * 3600 = 1 hr
+ *
+ * @var integer
+ * @access protected
+ */
+ protected $idleTime = 1800;
+
+ /**
+ * Authentication options for storage driver
+ *
+ * This is setup here, so it can be overridden in subclasses and merged
+ * into existing authentication options.
+ *
+ * @var array
+ * @access protected
+ */
+ protected $classOptions = array();
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * Sets up the storage driver
+ *
+ * @param string $storageDriver (optional)Type of the storage driver
+ * @param array $options (optional)Additional options for the
+ * storage driver
+ * @param string $loginFunction (optional)Name of the function that
+ * creates the login form
+ * @param boolean $showLogin (optional)Should the login form be
+ * displayed if neccessary?
+ *
+ * @return void
+ * @access public
+ */
+ public function __construct(
+ $storageDriver = 'DB',
+ array $options = array(),
+ $loginFunction = '',
+ $showLogin = true
+ ) {
+ // These are the default options, they are defined here b/c
+ // constants cannot be defined in the properites.
+ // subclasses that define any of the same authOptions will overwrite
+ // these when the options are merged. ALSO, options passed in
+ // via parameters will supercede/overwrite any of these authOptions
+ // or subclass authOptions.
+ $defaultOptions = array(
+ 'dsn' => DSN,
+ 'table' => 'contact',
+ 'usernamecol' => 'email',
+ 'passwordcol' => 'password',
+ 'db_fields' => array('id', 'fname', 'lname'),
+ 'cryptType' => 'md5',
+ );
+
+ $authOptions = array_merge(
+ $defaultOptions,
+ $this->classOptions,
+ $options
+ );
+
+ parent::Auth($storageDriver, $authOptions, $loginFunction, $showLogin);
+ }
+
+ // }}}
+
+ // {{{ loginForm()
+
+ /**
+ * Function to set up the regular login form
+ *
+ * @param unknown $uname Last attempted username
+ * @param unknown $status The authorization status
+ * @param unknown &$auth The authentication object
+ *
+ * @return void
+ * @access public
+ */
+ protected function loginForm($uname = null, $status = null, &$auth = null)
+ {
+ $login =& new TripPlannerLoginForm('member_login',
+ 'post',
+ BASE_URL . 'memberdb/index.php');
+ $login->setDbh(Toolkit_Database::getInstance());
+ $login->configureForm();
+ echo $login->toHtml();
+ }
+
+ // }}}
+
+ // {{{ passwordForm()
+
+ /**
+ * Function to set up the forgot password form
+ *
+ * @return void
+ * @access public
+ */
+ protected function passwordForm()
+ {
+ $pword =& new TripPlannerPasswordForm('member_password');
+ $pword->setDbh(Toolkit_Database::getInstance());
+ $pword->configureForm();
+ echo $pword->toHtml();
+ }
+
+ // }}}
+
+ // {{{ setIdle()
+
+ /**
+ * Set the maximum idle time
+ *
+ * @param integer $time time in seconds
+ * @param boolean $add (optional)add time to current maximum idle time or not
+ *
+ * @return void
+ * @access public
+ */
+ public function setIdle($time = null, $add = false)
+ {
+ $time = is_null($time) ? $this->idleTime : $time;
+ parent::setIdle($time, $add);
+ }
+
+ // }}}
+}
+
+/**
+ * Handles rendering and validating the member login form
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit_FormBuilder
+ */
+class TripPlannerLoginForm extends Toolkit_FormBuilder
+{
+ // {{{ properties
+
+ /**
+ * Custom rules to check for when validating the form
+ *
+ * @var array
+ * @access protected
+ */
+ protected $registeredRules = array();
+
+ /**
+ * Where to perform validation
+ *
+ * @var string
+ * @access protected
+ */
+ protected $validationType = 'client';
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * @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
+ * @param mixed $attributes (optional)Extra attributes for the
tag
+ * @param boolean $trackSubmit (optional)Whether to track if the form
+ * was submitted by adding a special hidden field
+ *
+ * @return void
+ * @access public
+ */
+ public function __construct(
+ $formName,
+ $method = 'post',
+ $action = '',
+ $target = '',
+ $attributes = null,
+ $trackSubmit = false
+ ) {
+ parent::__construct(
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+
+ $this->template = dirname(__FILE__) . '/templates/currentTables/';
+ }
+
+ // }}}
+
+ // {{{ configureElements()
+
+ /**
+ * Sets up the elements to be configured for use with the form
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureElements()
+ {
+ $e = array();
+
+ $e[] = array(
+ 'type' => 'header',
+ 'req' => false,
+ 'name' => 'formHdr',
+ 'display' => Toolkit_Members_Admin_Controller::$listingType['singular'] . ' Login'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'username',
+ 'display' => 'Username'
+ );
+ $e[] = array(
+ 'type' => 'password',
+ 'req' => true,
+ 'name' => 'password',
+ 'display' => 'Password'
+ );
+ $e[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'doLogin',
+ 'display' => 'Login now',
+ 'opts' => array('id' => 'doLogin')
+ );
+ $e[] = array(
+ 'type' => 'link',
+ 'req' => false,
+ 'name' => 'forgot',
+ 'display' => 'Forgot your password? Click',
+ 'opts' => BASE_URL . 'index.php?catid='.MEMBERS_CATEGORY.'&forgot=',
+ 'att' => 'here'
+ );
+
+ $this->setupElements($e);
+ }
+
+ // }}}
+ // {{{ configureFilters()
+
+ /**
+ * Sets up the filters to be used with the form when submitted
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureFilters()
+ {
+ $f = array();
+
+ $f[] = array(
+ 'element' => '__ALL__',
+ 'filter' => 'trim'
+ );
+ $this->setupFilters($f);
+ }
+
+ // }}}
+ // {{{ configureForm()
+
+ /**
+ * Helper method to setup form
+ *
+ * @return void
+ * @access public
+ */
+ public function configureForm()
+ {
+ $this->configureElements();
+ $this->configureFilters();
+ $this->configureRules();
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Sets up required rules and extra defined rules for the form
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureRules()
+ {
+ $this->setupRules($r);
+ }
+
+ // }}}
+
+ // {{{ setDbh()
+
+ /**
+ * set the pdo to use for db calls
+ *
+ * @param PDO $pdo PHP Data Object to use
+ *
+ * @return void
+ * @access public
+ */
+ public function setDbh(PDO $pdo)
+ {
+ $this->dbh = $pdo;
+ }
+
+ // }}}
+ // {{{ setupRenderers()
+
+ /**
+ * Inject custom renderers into the forms elements for custom display
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ parent::setupRenderers();
+
+ $renderer =& $this->defaultRenderer();
+ $required = '*';
+ $error = '
{error}
';
+
+ $renderer->setElementTemplate('
{label} {element}
', 'forgot');
+ $renderer->setElementTemplate('
{element}
', 'doLogin');
+ }
+
+ // }}}
+
+ // {{{ toHtml()
+
+ /**
+ * Returns an HTML version of the form
+ *
+ * @return string HTML version of the form
+ * @access public
+ */
+ public function toHtml()
+ {
+ $this->setupRenderers();
+ if ($this->validate()) {
+ header('Location: ' . BASE_URL . 'memberdb/index.php');
+ } elseif ($this->isSubmitted()) {
+ $output = $this->errorMsg;
+ $output .= parent::toHtml();
+ } else {
+ if ($_GET['status']) {
+ switch ($_GET['status']) {
+ case -1 :
+ $error = 'Your session has exceeded the maximum idle time';
+ break;
+
+ case -2 :
+ $error = 'Your session has expired.';
+ break;
+
+ case -3 :
+ $error = 'Invalid username or password.';
+ break;
+
+ case -4 :
+ // This is primarily used for Development.
+ // Users should never be presented with this error.
+ $error = 'Invalid Container';
+ break;
+
+ case -5 :
+ // This is only thrown if the advanced security system
+ // has detected a breach into the system.
+ $error = 'The system has encountered an error. Reference code: -5';
+ break;
+ }
+ $output = "
$error
";
+ }
+ $output .= parent::toHtml();
+ }
+
+ return $output;
+ }
+
+ // }}}
+}
+
+/**
+ * Handles rendering and validating the member password form
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit_FormBuilder
+ */
+class TripPlannerPasswordForm extends Toolkit_FormBuilder
+{
+ // {{{ properties
+
+ /**
+ * Table to query when gathering information
+ *
+ * @var string
+ * @access public
+ */
+ public $tableName = 'member';
+
+ /**
+ * Custom defined rules to validate against when the form is submitted
+ *
+ * @var array
+ * @access protected
+ */
+ protected $registeredRules = array();
+
+ /**
+ * Where to perform validation
+ *
+ * @var string
+ * @access protected
+ */
+ protected $validationType = 'client';
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * @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
+ * @param mixed $attributes (optional)Extra attributes for the
tag
+ * @param boolean $trackSubmit (optional)Whether to track if the form
+ * was submitted by adding a special hidden field
+ *
+ * @return void
+ * @access public
+ */
+ public function __construct(
+ $formName,
+ $method = 'post',
+ $action = '',
+ $target = '',
+ $attributes = null,
+ $trackSubmit = false
+ ) {
+ parent::__construct(
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+
+ $this->template = dirname(__FILE__) . '/templates/currentTables/';
+ }
+
+ // }}}
+
+ // {{{ checkAddressExists()
+
+ /**
+ * Checks to see if the email address exists before allowing an email to go out
+ *
+ * @param string $value submitted email address
+ *
+ * @return boolean If the email address exists or not
+ * @access public
+ */
+ public function checkAddressExists($value)
+ {
+ try {
+ $sql = "
+ SELECT count(*) AS total
+ FROM {$this->tableName}
+ WHERE member_contact_email = :mce";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':mce', $value, PDO::PARAM_STR);
+ $stmt->execute();
+ $stmt->bindColumn('total', $exists);
+ $stmt->fetch();
+
+ return (bool) $exists;
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ configureElements()
+
+ /**
+ * Sets up the elements to be configured for use with the form
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureElements()
+ {
+ $e = array();
+
+ $e[] = array(
+ 'type' => 'header',
+ 'req' => false,
+ 'name' => 'formHdr',
+ 'display' => 'Email Reminder'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'email',
+ 'display' => 'Your Member Contact Email Address'
+ );
+ $e[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'submit',
+ 'display' => 'Send'
+ );
+
+ $this->setupElements($e);
+ }
+
+ // }}}
+ // {{{ configureFilters()
+
+ /**
+ * Sets up the filters to be used with the form when submitted
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureFilters()
+ {
+ $f = array();
+
+ $f[] = array(
+ 'element' => '__ALL__',
+ 'filter' => 'trim'
+ );
+ $this->setupFilters($f);
+ }
+
+ // }}}
+ // {{{ configureForm()
+
+ /**
+ * Helper method to setup form
+ *
+ * @return void
+ * @access public
+ */
+ public function configureForm()
+ {
+ $this->configureElements();
+ $this->configureFilters();
+ $this->configureRules();
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Sets up required rules and extra defined rules for the form
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureRules()
+ {
+ $r = array();
+
+ $r[] = array(
+ 'element' => 'email',
+ 'message' => 'ERROR: Invalid Email Format!',
+ 'type' => 'email',
+ 'format' => null,
+ 'validation' => $this->validationType,
+ 'reset' => true,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => 'email',
+ 'message' => 'ERROR: Cannot locate email address!',
+ 'type' => 'callback',
+ 'format' => array(&$this,
+ 'checkAddressExists'),
+ 'validation' => $this->validationType,
+ 'reset' => true,
+ 'force' => false
+ );
+
+ $this->setupRules($r);
+ }
+
+ // }}}
+
+ // {{{ setDbh()
+
+ /**
+ * set the pdo to use for db calls
+ *
+ * @param PDO $pdo PHP Data Object to use
+ *
+ * @return void
+ * @access public
+ */
+ public function setDbh(PDO $pdo)
+ {
+ $this->dbh = $pdo;
+ }
+
+ // }}}
+ // {{{ setupRenderers()
+
+ /**
+ * Inject custom renderers into the forms elements for custom display
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ parent::setupRenderers();
+
+ $renderer =& $this->defaultRenderer();
+ $required = '*';
+ $error = '
{error}
';
+
+ $renderer->setElementTemplate('
{element}
', 'submit');
+ }
+
+ // }}}
+
+ // {{{ processData()
+
+ /**
+ * Processes the data submitted by the form
+ *
+ * Gets the login credentials for the matching email address and mails
+ * them to that email address
+ *
+ * @param array $values submitted form values
+ *
+ * @return boolean Result of mail
+ * @access protected
+ */
+ protected function processData($values)
+ {
+ try {
+ $sql = "
+ SELECT member_login, member_passwd
+ FROM {$this->tableName}
+ WHERE member_contact_email = :mce";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':mce', $values['email'], PDO::PARAM_STR);
+ $stmt->execute();
+ $row = $stmt->fetch();
+
+ $htmlMsg
+ = "Here is your " . SITENAME . " password:
+This section has been designed to allow you to build your own itinerary including attractions, recreation
+and places to stay in Michigan's Upper Peninsula. To get started, search for the recreation, attraction or
+place to stay on our Web site. As you find items that may be of interest to you, simply click the "Add to
+Trip Planner" icon on each business listing. Each item will then get added to your list. Once you have
+completed adding items to your planner list, you may take the following actions:
+
+
+
+
+
Request Info
+This action will send an email directly to each individual business using our "Send Me More Information"
+form. For the attractions, recreation or places to stay you have added to your list that do not have an
+email, you will be presented with the business name and their phone number.
+
+
Print This List
+You may print the full list of the items you have added to your travel planner, making it an easy reference
+to the business name, address, phone number, email address and Web site.
+
+
View Map
+View all of the items you have added to your trip planner on an interactive map, allowing you to get
+driving directions to each of those locations.
+
+
+
+Save your Trip Planner
+Create an account and SAVE your list for future reference.
+
');
+$dont_include_functions = true;
+/**
+ * requires setup.phtml
+ */
+require_once '../../../setup.phtml';
+
+HTTP_Session2::useCookies(false);
+HTTP_Session2::start();
+
+$tripPlannerAuth =& new Toolkit_Members_TripPlanner_TripAuth(
+ 'DB',
+ array(),
+ '',
+ false
+);
+$tripPlannerAuth->setIdle();
+$tripPlannerAuth->start();
+$sessionList = new Toolkit_Members_TripPlanner_Sessions(
+ Toolkit_Database::getInstance(),
+ &$tripPlannerAuth
+);
+if ($_SESSION['wish_list'][$_REQUEST['member_id']]) {
+ $sessionList->removeRecord($_REQUEST['member_id']);
+ $add = false;
+} else {
+ $sessionList->addRecord($_REQUEST['member_id'], $_REQUEST['catid']);
+ $add = true;
+}
+
+//remove the email from GET array and goback to member detail page
+unset($_REQUEST['member_email']);
+if (is_array($_REQUEST)) {
+ foreach ($_REQUEST as $pname => $pval) {
+ if ($pval) {
+ $param_part[] = $pname.'='.urlencode($pval);
+ }
+ }
+}
+if (is_array($param_part)) {
+ $params = implode("&", $param_part);
+}
+
+// need to make sure any GET parameter passed to this page get resent back
+$url = BASE_URL . "index.php?catid=".$_REQUEST['catid'];
+$url .= ($_REQUEST['detail']) ? "&member_id=" . $_REQUEST['member_id'] :'&_qf__SearchForm=';
+$url .= ($_REQUEST['search']) ? "&search=" . $_REQUEST['search'] :'';
+$url .= ($_REQUEST['business_name']) ?"&business_name=" . urlencode($_REQUEST['business_name']):'';
+$url .= ($_REQUEST['category_id']) ? "&category_id=" . $_REQUEST['category_id'] :'';
+$url .= ($_REQUEST['sub_category_id']) ? "&sub_category_id=" . $_REQUEST['sub_category_id'] :'';
+$url .= ($_REQUEST['region_id']) ? "®ion_id=" . $_REQUEST['region_id'] :'';
+$url .= ($_REQUEST['city_id']) ? "&city_id=" . $_REQUEST['city_id'] :'';
+$url .= ($_REQUEST['page']) ? "&page=" . $_REQUEST['page'] :'';
+$url .= ($_REQUEST['cPage']) ? "&cPage=" . $_REQUEST['cPage'] :'';
+$url .= ($_REQUEST['alpha']) ? "&alpha=" . $_REQUEST['alpha'] :'';
+$url .= ($_REQUEST['pageOffset']) ? "&pageOffset=" . $_REQUEST['pageOffset'] :'';
+$url .= ($add == true) ? '&sessionAdd=1': '&sessionAdd=2';
+header("location: $url");
+exit();
+?>
diff --git a/Toolkit/Members/TripPlannerList.php b/Toolkit/Members/TripPlannerList.php
new file mode 100644
index 0000000..902675d
--- /dev/null
+++ b/Toolkit/Members/TripPlannerList.php
@@ -0,0 +1,431 @@
+
+ * @copyright 2009 Gaslight Media
+ * @license Gaslight Media
+ * @version CVS: $Id: TripPlannerList.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link <>
+ */
+
+/**
+ * Short description for class
+ *
+ * Long description (if any) ...
+ *
+ * @category Toolkit
+ * @package Toolkit_Members
+ * @author Steve Sutton
+ * @copyright 2009 Gaslight Media
+ * @license Gaslight Media
+ * @version Release: @package_version@
+ * @link <>
+ */
+class Toolkit_Members_TripPlannerList
+{
+ // {{{ properties
+
+
+ /**
+ * Description for public
+ * @var string
+ * @access protected
+ */
+ public $dbh;
+
+ /**
+ * Template directory for any templates
+ * @var string
+ * @access protected
+ */
+ protected $templatesDir = 'templates';
+
+ /**
+ * compile directory for flexy
+ * @var string
+ * @access protected
+ */
+ protected $compiledDir = 'compiled';
+
+ protected $plannerListPageId;
+ protected $plannerFormPageId;
+
+ // }}}
+ // {{{ __construct()
+
+
+ /**
+ * class constructor
+ *
+ * Only setup values need be done here
+ * any work need to be done within methods
+ *
+ * @param object $pdo PDO reference
+ *
+ * @return void
+ * @access public
+ */
+ function __construct($pdo)
+ {
+ $this->dbh = $pdo;
+ // These settings are used to override flexyOptions.
+ $this->templatesDir = dirname(__FILE__) . "/{$this->templatesDir}";
+ $this->compiledDir = dirname(__FILE__) . "/{$this->compiledDir}";
+ $this->flexyConfig = $GLOBALS['flexyOptions'];
+ $this->flexyConfig['templateDir'] = $this->templatesDir;
+ $this->flexyConfig['compileDir'] = $this->compiledDir;
+ $this->pagerOptions['containerClass'] = 'pages';
+ $this->plannerListPageId = MEMBER_SESSION_PAGE;
+ $this->plannerFormPageId = MEMBER_SESSION_FORM;
+ }
+
+ // }}}
+ // {{{ getAncestors()
+
+ /**
+ * getAncestors:get the ancestors for this category
+ *
+ * @param integer $catid catid
+ * @param integer $count starting counter
+ *
+ * @return array
+ * @access public
+ */
+ function getAncestors($catid, $count = 0)
+ {
+ static $ancestors, $toolbox;
+ if (!$ancestors || $count == 0) {
+ $ancestors = array();
+ }
+ if (!$toolbox) {
+ $toolbox = new GLM_TEMPLATE(HOME_ID);
+ }
+ if ($catid) {
+ $sql = "
+ SELECT id, category, parent
+ FROM bus_category
+ WHERE id = :catid";
+ try {
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(":catid", $catid, PDO::PARAM_INT);
+ $stmt->execute();
+ $res = $stmt->fetch();
+ $ancestors[$count]['id'] = $res['id'];
+ $ancestors[$count]['label'] = $res['category'];
+ } catch(PDOException $e) {
+ ToolkitCommon::handleError($e);
+ }
+
+ $url = $toolbox->get_seo_url($res['id']);
+ $ancestors[$count]['link'] = $url;
+ $this->getAncestors($res['parent'], ++$count);
+
+ return array_reverse($ancestors);
+ }
+ }
+
+ // }}}
+ // {{{ getSessionList()
+
+
+ /**
+ * get list from session
+ *
+ * @return void
+ * @access public
+ */
+ function getSessionList()
+ {
+ // for the session list need to sort by categories then
+ // we'll have to go through the session first and organize to what category they're in
+ // then run query
+ // have to order by the page name we'll need to find there names first then
+ $sql = "
+ SELECT category
+ FROM bus_category
+ WHERE id = :category_id";
+ $getCatName = $this->dbh->prepare($sql);
+ $sql = "
+ SELECT member_name
+ FROM member
+ WHERE member_id = :member_id";
+ $getMemberName = $this->dbh->prepare($sql);
+ if (is_array($_SESSION['wish_list']) && !empty($_SESSION['wish_list'])) {
+ foreach ($_SESSION['wish_list'] as $member_id => $mData) {
+ try {
+ $getCatName->bindParam(":category_id", $mData['catid'], PDO::PARAM_INT);
+ $getCatName->execute();
+ $toolboxPageName = $getCatName->fetchColumn();
+ $getMemberName->bindParam(":member_id", $member_id, PDO::PARAM_INT);
+ $getMemberName->execute();
+ $memberName = $getMemberName->fetchColumn();
+ $members[$toolboxPageName][$memberName] = $member_id;
+ } catch(PDOException $e) {
+ ToolkitCommon::handleError($e);
+ }
+ }
+ // for sorting members by the page they're added from
+ natSort(&$members);
+ try {
+ $sql = "
+ SELECT m.*, c.city_name AS city, s.state_name AS state,
+ s.state_abb AS state_abbr,
+ m.street||', '||c.city_name||', '||s.state_name||', '||m.zip AS address
+ FROM member m
+ JOIN state s USING (state_id)
+ JOIN city c USING (city_id)
+ WHERE member_id = :member_id";
+ $stmt = $this->dbh->prepare($sql);
+ if (is_array($members)) {
+ $count = 0;
+ foreach ($members as $toolbboxPageName => $memberList) {
+ // for sorting members under each page
+ natSort(&$memberList);
+ foreach ($memberList as $memberName => $member_id) {
+ $stmt->bindParam(":member_id", $member_id, PDO::PARAM_INT);
+ $stmt->execute();
+ // set record data
+ $catid = $_SESSION['wish_list'][$member_id]['catid'];
+ $recordSet[$count] = $stmt->fetch();
+ // setup the breadCrumbs
+ $recordSet[$count]['breadCrumbs'] = $this->printAncestors($catid);
+ // setup delete link
+ $recordSet[$count]['deleteUrl'] = BASE_URL .
+ 'wish-list.php?catid=' . $_REQUEST['catid'] .
+ '&member_id=' . $member_id;
+ // setup the url
+ $recordSet[$count]['urlText'] = $recordSet[$count]['url'];
+ if ($recordSet[$count]['url']) {
+ $recordSet[$count]['url'] = BASE_URL .
+ 'Toolkit/Members/memberClickThru.php' .
+ '?member_id=' . $member_id .
+ '&href=' . urlencode($recordSet[$count]['url']);
+ }
+ ++$count;
+ }
+ }
+ if (is_array($recordSet)) {
+ $temp = new HTML_Template_Flexy($this->flexyConfig);
+ $page = new stdClass;
+ $toolbox = new GLM_TEMPLATE(HOME_ID);
+ $page->accountUrl = $toolbox->get_seo_url($this->plannerFormPageId);
+ $page->loginUrl = BASE_URL . 'Toolkit/Members/TripPlanner/login.php';
+ $page->logoutUrl = BASE_URL . 'Toolkit/Members/TripPlanner/login.php?logout=1';
+ $page->saveUrl = BASE_URL . 'index.php?catid='.$this->plannerListPageId.'&cPage=Save+List';
+ $page->requestUrl = BASE_URL . 'index.php?catid='.$this->plannerListPageId.'&cPage=Send+List';
+ $page->loginStat = ($_REQUEST['status']) ? 'Invalid username or password.': '';
+ $page->isLoggedIn = $this->isLoggedIn();
+ $page->username = $page->isLoggedIn;
+ $page->baseurl = BASE_URL;
+ $page->recordSet = $recordSet;
+ $page->numberedSet = count($recordSet);
+ $temp->compile("tripPlannerList.tpl");
+ $out .= $temp->BufferedOutputObject($page);
+ }
+ }
+ //echo '
'.print_r($page, true).'
';
+ echo $out;
+ } catch(PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ } else {
+ echo $this->showEmpty();
+ }
+ }
+
+ // }}}
+ // {{{ isLoggedIn()
+
+ /**
+ * check if user is logged in or not
+ *
+ * @access public
+ * @return string
+ */
+ function isLoggedIn()
+ {
+ $tripPlannerAuth =& new Toolkit_Members_TripPlanner_TripAuth('DB', array(), '', false);
+ $tripPlannerAuth->setIdle();
+ $tripPlannerAuth->start();
+
+ $test = $tripPlannerAuth->checkAuth();
+ if ($test) {
+ // give back the username
+ return $tripPlannerAuth->getUsername();
+ } else {
+ return false;
+ }
+ }
+
+ // }}}
+ // {{{ printAncestors()
+
+ /**
+ * printAncestors
+ *
+ * @param mixed $catid page id
+ *
+ * @access public
+ * @return string
+ */
+ function printAncestors($catid)
+ {
+ $ancestors = $this->getAncestors($catid, 0);
+ if (is_array($ancestors)) {
+ for ($i = 0; $i < count($ancestors); ++$i) {
+ $out[] = '' . $ancestors[$i]["label"] . '';
+ }
+ if (is_array($out)) {
+ return implode(" / ", $out);
+ }
+ }
+ }
+
+ // }}}
+ // {{{ saveList()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @return string Return description (if any) ...
+ * @access public
+ */
+ function saveList()
+ {
+ if ($this->isLoggedIn()) {
+ $contactId = $_SESSION['_authsession']['data']['id'];
+ // if they already have something saved then wipe it out.
+ // (only one list per contact)
+ try {
+ $sql = "
+ DELETE FROM member_session
+ WHERE contact_id = :contact_id";
+ $del = $this->dbh->prepare($sql);
+ $del->bindParam(":contact_id", $contactId, PDO::PARAM_INT);
+ $del->execute();
+ } catch(PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+
+ $sql = "
+ INSERT INTO member_session
+ (member_id,contact_id,catid)
+ VALUES
+ (:member_id,:contact_id,:catid)";
+ $stmt = $this->dbh->prepare($sql);
+ if (is_array($_SESSION['wish_list'])) {
+ foreach ($_SESSION['wish_list'] as $member_id => $mData) {
+ $catid = $mData['catid'];
+ try {
+ $stmt->bindParam(":member_id", $member_id, PDO::PARAM_INT);
+ $stmt->bindParam(":contact_id", $contactId, PDO::PARAM_INT);
+ $stmt->bindParam(":catid", $catid, PDO::PARAM_INT);
+ $stmt->execute();
+ } catch(PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+ $html = '
You list has been saved.
';
+ }
+ }
+ return $html;
+ }
+
+ // }}}
+ // {{{ show()
+
+
+ /**
+ * Calls the appropiate function for listing,saving,sending
+ * or printing the list also will need to handle grabbing list from
+ * database and repopulate the session.
+ *
+ * @return void
+ * @access public
+ */
+ function show()
+ {
+ echo $this->toHTML();
+ }
+
+ // }}}
+ // {{{ showEmpty()
+
+ /**
+ * shows the template tripPlannerNoList.tpl
+ *
+ * @access public
+ * @return string
+ */
+ function showEmpty()
+ {
+ $temp = new HTML_Template_Flexy($this->flexyConfig);
+ $temp->compile("tripPlannerNoList.tpl");
+ $page = new stdClass;
+ $toolbox = new GLM_TEMPLATE(HOME_ID);
+ $page->accountUrl = $toolbox->get_seo_url($this->plannerFormPageId);
+ $page->loginUrl = BASE_URL . 'Toolkit/Members/TripPlanner/login.php';
+ $page->logoutUrl = BASE_URL . 'Toolkit/Members/TripPlanner/login.php?logout=1';
+ $page->saveUrl = BASE_URL . 'index.php?catid='.$this->plannerListPageId.'&cPage=Save+List';
+ $page->requestUrl = BASE_URL . 'index.php?catid='.$this->plannerListPageId.'&cPage=Send+List';
+ $page->loginStat = ($_REQUEST['status']) ? 'Invalid username or password.': '';
+ $page->isLoggedIn = $this->isLoggedIn();
+ $page->username = $page->isLoggedIn;
+ $page->baseurl = BASE_URL;
+ return $temp->BufferedOutputObject($page);
+ }
+
+ // }}}
+ // {{{ toHTML()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @return string Return description (if any) ...
+ * @access public
+ */
+ function toHTML()
+ {
+ if (is_array($_SESSION['wish_list']) && !empty($_SESSION['wish_list'])) {
+ switch ($_REQUEST['cPage']) {
+ case "Send List":
+ $pp = new Toolkit_Contacts_SendTripPlanner($this->dbh,
+ 'TravelList',
+ 'post',
+ BASE_URL .
+ 'index.php?catid='.$this->plannerListPageId);
+ $pp->configureForm();
+ $html = $pp->toHTML();
+ break;
+ case "Save List":
+ $html = $this->saveList();
+ $html .= $this->getSessionList();
+ break;
+ case "Login":
+ break;
+ case "Show List":
+ default:
+ $html = $this->getSessionList();
+ break;
+ }
+ } else {
+ echo $this->showEmpty();
+ }
+ return $html;
+ }
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/UserSearchForm.php b/Toolkit/Members/UserSearchForm.php
new file mode 100644
index 0000000..572a0d9
--- /dev/null
+++ b/Toolkit/Members/UserSearchForm.php
@@ -0,0 +1,775 @@
+
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: UserSearchForm.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Member Search Form
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Members_UserSearchForm
+ extends Toolkit_FormBuilder implements Toolkit_Form
+{
+ // {{{ properties
+
+
+ /**
+ * Description for protected
+ * @var array
+ * @access protected
+ */
+ protected $memberCatsAssignedToPage = array();
+
+ /**
+ * The Table name used to store the data of the member record in the database.
+ *
+ * @var string
+ * @access public
+ */
+ public $tableName = 'member';
+
+ /**
+ * Array of data that holds the meta data info on the table
+ *
+ * Contains information on the type of fields in the database.
+ * That way when we run our automated SQL queries with our PDO
+ * we can properly bind data to our SQL queries. This will
+ * allow for one more layer of protection against any sql
+ * injection attempts.
+ *
+ * @var string
+ * @access public
+ */
+ public $tableMetaData;
+
+ /**
+ * Flexy options used in the renderer
+ *
+ * @var array
+ * @access protected
+ */
+ protected $flexyOptions;
+
+ /**
+ * The name of the template used to render the member info form
+ *
+ * @var string
+ * @access protected
+ */
+ protected $formTemplate = 'memberSearchForm.tpl';
+
+ /**
+ * Form access from inside the template
+ *
+ * @var object
+ * @access protected
+ */
+ protected $view;
+
+ /**
+ * registered rules for the form
+ *
+ * @var array
+ * @access protected
+ */
+ protected $registeredRules = array();
+
+ /**
+ * catid to use in the form
+ *
+ * @var integer
+ * @access private
+ */
+ private $_catid;
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Class constructor
+ *
+ * @param PDO $pdo PHP Data Object for DB calls
+ * @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
+ ) {
+ parent::__construct(
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+
+ $this->dbh = $pdo;
+ $this->flexyOptions = Toolkit_Members::getFlexyOptions();
+ }
+
+ // }}}
+
+ // {{{ configureConstants()
+
+ /**
+ * Sets the constants for the form
+ *
+ * The member category select list must always default
+ * to the -- Choose Category -- option
+ *
+ * @return void
+ * @access public
+ */
+ public function configureConstants()
+ {
+ $c = array(
+ 'catid' => $this->_catid,
+ 'search' => 1,
+ );
+
+ $this->setupConstants($c);
+ }
+
+ // }}}
+ // {{{ configureDefaults()
+
+ /**
+ * Sets the defaults for the an existing member
+ *
+ * Populates data for the main member form. Also grabs
+ * data to populate the modules on the form if needed.
+ *
+ * @return array $defaults Returns the array of defaults
+ * so children who call this function
+ * can obtain a copy of these values.
+ * @access public
+ */
+ public function configureDefaults()
+ {
+ $d = array();
+
+ $this->setupDefaults($d);
+
+ return $d;
+ }
+
+ // }}}
+ // {{{ configureElements()
+
+ /**
+ * Setup the elements to use on the form.
+ *
+ * @param Config_Container $c Configuration object
+ *
+ * @return void
+ * @access public
+ */
+ public function configureElements(Config_Container $c)
+ {
+ $e = array();
+
+ // get reference to [listing type] section of config file
+ $config =& $c->getItem('section', 'listing type');
+ $singularDirective =& $config->getItem('directive', 'singular');
+ $singularType = $singularDirective->getContent();
+ $pluralDirective =& $config->getItem('directive', 'plural');
+ $pluralType = $pluralDirective->getContent();
+
+ $memberCategories = $this->getMemberCats();
+ $memberSubCategories
+ = $this->getMemberSubCats($memberCategories, $_GET['category_id']);
+ $memberAmenities = $this->getMemberAmenities();
+
+ $cities = $this->getAvailableCities();
+ $this->createAvailableMemberTypesFromCity($cities);
+
+ // All Grouped Elements are created here.
+ foreach ($memberAmenities as $k => $v) {
+ $amenities[] = array(
+ 'type' => 'checkbox',
+ 'req' => false,
+ 'name' => $v,
+ 'display' => $k
+ );
+ }
+
+ // All Elements are created here. This includes group element definitions.
+ $e[] = array(
+ 'type' => 'header',
+ 'req' => false,
+ 'name' => 'SearchForm_hdr'
+ );
+ $e[] = array(
+ 'type' => 'hidden',
+ 'req' => false,
+ 'name' => 'catid'
+ );
+ $e[] = array(
+ 'type' => 'hidden',
+ 'req' => false,
+ 'name' => 'search'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'member_name',
+ 'display' => "$singular Name",
+ 'opts' => array('class' => 'text')
+ );
+ $e[] = array(
+ 'type' => 'select',
+ 'req' => false,
+ 'name' => 'city_id',
+ 'display' => 'City',
+ 'opts' => array('' => '-- Select --') + $cities,
+ );
+ $e[] = array(
+ 'type' => 'select',
+ 'req' => false,
+ 'name' => 'category_id',
+ 'display' => "$singular Type",
+ 'opts' => array('' => '-- Select --') + $memberCategories
+ );
+ $e[] = array(
+ 'type' => 'select',
+ 'req' => false,
+ 'name' => 'sub_category_id',
+ 'display' => "$singular Sub Type",
+ 'opts' => array('' => '-- Select --') + $memberSubCategories
+ );
+ // Only show do if we have amenities to show.
+ if (!empty($memberAmenities)) {
+ $e[] = array(
+ 'type' => 'group',
+ 'req' => false,
+ 'name' => 'amenities',
+ 'group' => $amenities,
+ 'seperator' => '',
+ 'appendName' => true
+ );
+ $e[] = array(
+ 'type' => 'checkbox',
+ 'req' => false,
+ 'name' => 'search_all_amenity',
+ 'opts' => 'Only show members who offer all selected amenities'
+ );
+ }
+
+ $this->setupElements($e);
+ }
+
+ // }}}
+ // {{{ configureFilters()
+
+ /**
+ * Setup the filters to apply to the elements before we are
+ * handed the values submitted
+ *
+ * @return void
+ * @access public
+ */
+ public function configureFilters()
+ {
+ $f = array();
+
+ $f[] = array(
+ 'element' => '__ALL__',
+ 'filter' => 'trim'
+ );
+
+ $this->setupFilters($f);
+ }
+
+ // }}}
+ // {{{ configureForm()
+
+ /**
+ * Helper method to configure the entire form
+ *
+ * @param Config_Container $c Configuration object
+ *
+ * @return void
+ * @access public
+ */
+ public function configureForm(Config_Container $c)
+ {
+ $this->configureElements($c);
+ $this->configureRules();
+ $this->configureFilters();
+ $this->configureDefaults();
+ $this->configureConstants();
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Sets up all the rules to be used when the form is validated.
+ *
+ * @return void
+ * @access public
+ */
+ public function configureRules()
+ {
+ $this->setupRules($rules);
+ }
+
+ // }}}
+ // {{{ createAvailableMemberTypesFromCity()
+
+ /**
+ * Get available categories from members assigned to cities
+ *
+ * @param array $cities Available cities to get members from
+ *
+ * @return void
+ * @access protected
+ */
+ protected function createAvailableMemberTypesFromCity(array $cities)
+ {
+ try {
+ $cityCats = array();
+
+ $availCats = array();
+ foreach ($this->memberCatsAssignedToPage as $i) {
+ $cats = Toolkit_Common::getHierarchicalTreeStructure(
+ 'category',
+ 'category_id',
+ 'parent_id',
+ 'pos',
+ $i,
+ 0,
+ false
+ );
+
+ $availCats = array_merge($availCats, array_keys($cats));
+ }
+ $availCats = implode(', ', $availCats);
+
+ $sql = "
+ SELECT distinct c.category_id, c.parent_id, p.name AS
+ parent, c.name AS category
+ FROM category c
+ JOIN category p
+ ON c.parent_id = p.category_id
+ JOIN member_category mc
+ ON c.category_id = mc.category_id
+ NATURAL JOIN member m
+ WHERE m.city_id = :cid
+ AND c.category_id in ($availCats)
+ ORDER BY c.name";
+ $stmt = $this->dbh->prepare($sql);
+ foreach ($cities as $i => $j) {
+ if (is_numeric($i)) {
+ $stmt->bindParam(':cid', $i, PDO::PARAM_INT);
+ $stmt->execute();
+ $row = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ foreach ($row as $x) {
+ $cityCats[$i][$x['parent_id']][$x['category_id']] = $x['category'];
+ $mainCats[$x['parent_id']] = $x['parent'];
+ }
+
+ }
+ }
+
+ $this->cityCategories = $cityCats;
+ $this->mainCats = $mainCats;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ getAvailableCities()
+
+ /**
+ * Returns all available cities that derive from members assigned to
+ * this page
+ *
+ * @return array array of cities available to this page
+ * @access protected
+ */
+ protected function getAvailableCities()
+ {
+ try {
+ $memCats = array();
+ foreach ($this->memberCatsAssignedToPage as $i) {
+ $cats = Toolkit_Common::getHierarchicalTreeStructure(
+ 'category',
+ 'category_id',
+ 'parent_id',
+ 'pos',
+ $i,
+ 0,
+ false
+ );
+
+ $memCats = array_merge($memCats, array_keys($cats));
+ }
+ $memCats = implode(', ', $memCats);
+ $sql = "
+ SELECT region
+ FROM bus_category
+ WHERE id = :catid";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':catid', $_GET['catid'], PDO::PARAM_INT);
+ $stmt->execute();
+ $stmt->bindColumn('region', $county);
+ $stmt->fetch();
+ if (is_numeric($county)) {
+ $county = "AND region_id = $county";
+ }
+ $sql = "
+ SELECT *
+ FROM city
+ WHERE city_id in (
+ SELECT distinct(city_id)
+ FROM member
+ WHERE member_id in (
+ SELECT distinct(member_id)
+ FROM member_category
+ WHERE category_id IN ($memCats)
+ )
+ )
+ $county
+ ORDER BY city_name";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->execute();
+ $cities = array();
+ while ($row = $stmt->fetch()) {
+ $cities[$row['city_id']] = $row['city_name'];
+ }
+
+ asort($cities);
+ return $cities;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ getMemberAmenities()
+
+ /**
+ * Get all the amenities for the member
+ *
+ * @return array member amenities
+ * @access protected
+ */
+ protected function getMemberAmenities()
+ {
+ try {
+ $amenities = array();
+
+ $sql = "
+ SELECT *
+ FROM amenity a
+ NATURAL JOIN member_amenity ma
+ NATURAL JOIN member_category mc
+ WHERE mc.category_id = :cid
+ OR mc.category_id in (
+ SELECT category_id
+ FROM category
+ WHERE parent_id = :cid)
+ ORDER BY amenity_name";
+
+ $stmt = $this->dbh->prepare($sql);
+ foreach ($this->memberCatsAssignedToPage as $id) {
+ $stmt->bindParam(':cid', $id, PDO::PARAM_INT);
+ $stmt->execute();
+ while ($row = $stmt->fetch()) {
+ $amenities[$row['amenity_name']] = $row['amenity_id'];
+ }
+ }
+
+ return $amenities;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ getMemberCats()
+
+ /**
+ * Get all the main categories available from the categories that
+ * are assigned to the page.
+ *
+ * If a main category is assigned to a page, then add to list.
+ *
+ * If a sub category is assgined to page, then add parent (main) category
+ * to the list.
+ *
+ * @return array Main categories available for page
+ * @access protected
+ */
+ protected function getMemberCats()
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM category
+ WHERE category_id = :cid";
+
+ $stmt = $this->dbh->prepare($sql);
+ $categories = array();
+ foreach ($this->memberCatsAssignedToPage as $id) {
+ $stmt->bindParam(':cid', $id, PDO::PARAM_INT);
+ $stmt->execute();
+ if ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ if ($row['parent_id'] == '0') {
+ $categories[$row['category_id']] = $row['name'];
+ } else {
+ $stmt->bindParam(':cid', $row['parent_id'], PDO::PARAM_INT);
+ $stmt->execute();
+ if ($parRow = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $categories[$parRow['category_id']] = $parRow['name'];
+ }
+ }
+ }
+ }
+ asort($categories);
+ return $categories;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ getMemberSubCats()
+
+ /**
+ * Get all the sub categories available from the main categories that
+ * are available to the page.
+ *
+ * @param array $categories Main level categories to get sub levels for
+ * @param integer $parentIdKey (optional) Main level that was searched on
+ *
+ * @return array Sub categories available for page
+ * @access protected
+ */
+ protected function getMemberSubCats(array $categories, $parentIdKey = null)
+ {
+ if (empty($categories)) {
+ return array();
+ }
+
+ try {
+ // Get the category information
+ $sql = "
+ SELECT *
+ FROM category
+ WHERE category_id = :cid";
+
+ $catStmt = $this->dbh->prepare($sql);
+
+ // Get the sub-category information
+ $sql = "
+ SELECT *
+ FROM category
+ WHERE parent_id = :parent_id";
+ $subCatStmt = $this->dbh->prepare($sql);
+ $subCategories = array();
+
+ while (list($id,) = each($categories)) {
+ $catStmt->bindParam(':cid', $id, PDO::PARAM_INT);
+ $catStmt->execute();
+ $category = $catStmt->fetch();
+ try {
+ $subCatStmt->bindParam(
+ ':parent_id',
+ $category['category_id'],
+ PDO::PARAM_INT
+ );
+ $subCatStmt->execute();
+ if ($subCatData = $subCatStmt->fetchAll()) {
+ foreach ($subCatData as $key => $val) {
+ $catStmt->bindParam(
+ ':cid',
+ $val['category_id'],
+ PDO::PARAM_INT
+ );
+ $catStmt->execute();
+ $subCat = $catStmt->fetch();
+ if (in_array($subCat['category_id'], $this->memberCatsAssignedToPage)) {
+ // Subcat assgined to page, only assign
+ // child of parent cat that is assigned
+ // to page.
+ $subCategories[$subCat['parent_id']][$subCat['category_id']] = $subCat['name'];
+ } elseif (in_array($subCat['parent_id'], $this->memberCatsAssignedToPage)) {
+ // Parent category assigned to page, add all
+ // children found
+ $subCategories[$subCat['parent_id']][$subCat['category_id']] = $subCat['name'];
+ }
+ }
+ }
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ if ( is_numeric($parentIdKey)
+ && array_key_exists($parentIdKey, $subCategories)
+ ) {
+ return $subCategories[$parentIdKey];
+ } else {
+ $subCategories
+ = Toolkit_Common::arrayFlatten($subCategories, 2);
+ asort($subCategories);
+ return $subCategories;
+ }
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+
+ // {{{ toHtml()
+
+ /**
+ * Renders the form
+ *
+ * sets the page the form should be redirected to instead of coming back
+ * around to itself.
+ *
+ * @return string The rendered form
+ * @access public
+ */
+ public function toHtml()
+ {
+ // We need to validate (and freeze if needed)
+ // before we render the form. That way the
+ // template knows about any errors on the form.
+ $this->validated = $this->validate();
+
+ $this->legend
+ = GLM_TEMPLATE::get_catheader($this->_catid, new GLM_DB());
+
+ // ProcessData handles settingup the lat/lon coordinates if they were not entered
+ // into the form. these values ar calculated and then inserted into the forms
+ // element values. So we need to process the data first and then render the form.
+ $this->setupRenderers();
+
+ return $this->template->bufferedOutputObject($this->view);
+ }
+
+ // }}}
+
+ // {{{ setCatId()
+
+ /**
+ * set the catid to use in the form
+ *
+ * @param integer $catid page catid
+ *
+ * @return PEAR Error return a PEAR error if an invalid catid is passed in
+ * @access public
+ */
+ public function setCatId($catid)
+ {
+ if (is_numeric($catid) && ctype_digit((string) $catid)) {
+ $this->_catid = $catid;
+ } else {
+ return PEAR::raiseError('Invalid catid');
+ }
+ }
+
+ // }}}
+ // {{{ setPageMemberCategories()
+
+ /**
+ * Relate toolbox categories with main member categories
+ *
+ * @return array toolbox -> category relations
+ * @access public
+ */
+ public function setPageMemberCategories()
+ {
+ try {
+ $categoryToolbox = array();
+ $sql = "
+ SELECT bcm.*
+ FROM bus_cat_member bcm, category c
+ WHERE bcm.catid = :catid
+ AND bcm.memb_type = c.category_id
+ ORDER BY c.name";
+
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':catid', $this->_catid, PDO::PARAM_INT);
+ $stmt->execute();
+ while ($row = $stmt->fetch()) {
+ $categoryToolbox[] = $row['memb_type'];
+ }
+
+ $this->memberCatsAssignedToPage = $categoryToolbox;
+
+ return $categoryToolbox;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ setupRenderers()
+
+ /**
+ * Sets up the Flexy template
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ $renderer =& new HTML_QuickForm_Renderer_Object(true);
+
+ $this->accept($renderer);
+
+ $this->template =& new HTML_Template_Flexy($this->flexyOptions);
+
+ // Make the view a copy of the $this object
+ // That way we have access to call functions in
+ // this class from within the template.
+ $this->view = $this;
+ $this->view->form = $renderer->toObject();
+ $this->template->compile($this->formTemplate);
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Members/addressHelp.html b/Toolkit/Members/addressHelp.html
new file mode 100644
index 0000000..a143bb0
--- /dev/null
+++ b/Toolkit/Members/addressHelp.html
@@ -0,0 +1,10 @@
+
My business is not in the correct spot in Google Maps. What can I do?
+
+
Google provides the tools needed for placing your business correctly on their maps.
+Visit this page: http://www.google.com/lbc
+
In addition to your correct location in their maps, you can also add other information pertaining
+to your business such as opening hours, services, contact information etc.
+
+
What is the Latitude/Longitude fields on this page.
+
You can use this option to set your lat/long information for the Google Maps on this site only.
+
Once your location is displaying right from the Google Local Business Center, you can remove numbers in these fields.
diff --git a/Toolkit/Members/export-images-is0.php b/Toolkit/Members/export-images-is0.php
new file mode 100755
index 0000000..34bb34a
--- /dev/null
+++ b/Toolkit/Members/export-images-is0.php
@@ -0,0 +1,81 @@
+
+ * @author Jamie Kahgee
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: export-images-is0.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ * @see References to other sections (if any)...
+ */
+
+/**
+ * setup file
+ */
+require_once '../../setup.phtml';
+
+/**
+ * Image Server API
+ */
+require_once BASE.'Toolkit/Image/Server.php';
+
+$db = new PDO('pgsql:'.CONN_STR);
+
+/**
+ * Description for define
+ */
+define('OLDORG', 'http://demo.gaslightmedia.com/images/member_original/');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+$sql = "
+ SELECT member_id, logo
+ FROM member
+ WHERE logo != ''
+ AND logo not like 'is%'
+ ORDER BY member_id";
+try {
+ $stmt = $db->query($sql);
+ $data = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ echo '
';
+ print_r($data);
+ echo '
';
+} catch(PDOException $e) {
+ die($e->getMessage());
+}
+$db->beginTransaction();
+$IServer = new Toolkit_Image_Server();
+if (is_array($data)) {
+ $prep2 = "
+ UPDATE member
+ SET logo = :image
+ WHERE member_id = :id";
+ $stmt3 = $db->prepare($prep2);
+
+ foreach ($data as &$row) {
+ $row['logo'] = trim($row['logo']);
+ var_dump(OLDORG.$row['logo']);
+ if (!ereg("^is", $row['logo'])) {
+ $image_URL = OLDORG.urlencode($row['logo']);
+ $image = $IServer->imageUpload($image_URL);
+ if ($image) {
+ try {
+ $stmt3->bindParam(":image", $image, PDO::PARAM_STR);
+ $stmt3->bindParam(":id", $row['member_id'], PDO::PARAM_INT);
+ $stmt3->execute();
+ } catch(PDOException $e) {
+ die($e->getMessage());
+ }
+ }
+ echo ' Image Name Returned: ';
+ var_dump($image);
+ }
+ }
+}
+//$db->commit();
+$db->rollBack();
+?>
diff --git a/Toolkit/Members/libjs/authorizeChanges.js b/Toolkit/Members/libjs/authorizeChanges.js
new file mode 100644
index 0000000..9d545f3
--- /dev/null
+++ b/Toolkit/Members/libjs/authorizeChanges.js
@@ -0,0 +1,34 @@
+/**
+ * setup fckeditor for any textarea field that might exists on the page.
+ */
+var AuthorizeChanges =
+{
+ baseUrl: null,
+
+ init: function()
+ {
+ AuthorizeChanges.baseUrl = location.protocol + '//' + location.hostname + '/';
+
+ var url = location.pathname;
+ if (location.hostname == 'devsys2.gaslightmedia.com') {
+ var urlParts = url.split('/');
+ AuthorizeChanges.baseUrl += urlParts[1] + '/';
+ } else if (location.hostname == 'kanga.acrewoods.com') {
+ var site = location.pathname.split('/');
+ var urlParts = url.split('/');
+ AuthorizeChanges.baseUrl += urlParts[1] + '/' + site[2] + '/';
+ }
+
+ $('textarea').each(function(t) {
+ var id = $(this).attr('id');
+ if (id != null) {
+ var oFCKeditor = new FCKeditor(id);
+ oFCKeditor.BasePath = AuthorizeChanges.baseUrl + 'fckeditor/';
+ oFCKeditor.ToolbarSet = 'LimitedToolset';
+ oFCKeditor.ReplaceTextarea();
+ }
+ });
+ }
+}
+
+$(document).ready(AuthorizeChanges.init);
diff --git a/Toolkit/Members/libjs/business-detail.js b/Toolkit/Members/libjs/business-detail.js
new file mode 100755
index 0000000..d562cd1
--- /dev/null
+++ b/Toolkit/Members/libjs/business-detail.js
@@ -0,0 +1,80 @@
+var GDirs =
+{
+ baseUrl: null,
+ dBox: null,
+ originalText: null,
+ addyBox: null,
+
+ init: function()
+ {
+ GDirs.baseUrl = location.protocol + '//' + location.hostname + '/';
+ var url = location.pathname;
+ if (location.hostname == 'devsys2.gaslightmedia.com') {
+ var urlParts = url.split('/');
+ GDirs.baseUrl += urlParts[1] + '/';
+ } else if (location.hostname == 'kanga.acrewoods.com') {
+ var site = location.pathname.split('/');
+ var urlParts = url.split('/');
+ GDirs.baseUrl += urlParts[1] + '/' + site[2] + '/';
+ }
+
+ GDirs.addyBox = $('#toaddress');
+ GDirs.originalText = GDirs.addyBox.val();
+ GDirs.dBox = $('#google-div');
+ GDirs.dBox.before(' Directions ');
+ GDirs.dBox.hide();
+ $('#google-map-link').bind('click', GDirs.toggleBox);
+ $('#GDirs').bind('submit', GDirs.submitForm);
+ GDirs.addyBox.bind('focus', GDirs.clearForm);
+ GDirs.addyBox.bind('blur', GDirs.fillForm);
+ },
+
+ toggleBox: function(event)
+ {
+ event.preventDefault();
+ GDirs.dBox.slideToggle('normal');
+ },
+
+ submitForm: function(event)
+ {
+ if (GDirs.addyBox.val() == GDirs.originalText || GDirs.addyBox.val() == '') {
+ event.preventDefault();
+ alert('Please fill in your Address');
+ }
+ },
+
+ clearForm: function(event)
+ {
+ if (GDirs.addyBox.val() == GDirs.originalText) {
+ GDirs.addyBox.val('');
+ }
+ },
+
+ fillForm: function(event)
+ {
+ if (GDirs.addyBox.val() == '') {
+ GDirs.addyBox.val(GDirs.originalText);
+ }
+ }
+};
+
+var Imgs =
+{
+ init: function()
+ {
+ $('.member-img-s').bind('click', Imgs.updateImage);
+ },
+
+ updateImage: function(event)
+ {
+ $(this).effect('transfer', {to: "#member-img-1"}, 300);
+ $(this).queue(function() {
+ $('#member-img-1').attr('src', $(this).attr('id'));
+ $('#photo-caption').text($(this).attr('alt'));
+ $(this).dequeue();
+ });
+ }
+};
+
+$(document).ready(GDirs.init);
+$(document).ready(Imgs.init);
diff --git a/Toolkit/Members/libjs/business-search.js b/Toolkit/Members/libjs/business-search.js
new file mode 100644
index 0000000..9135489
--- /dev/null
+++ b/Toolkit/Members/libjs/business-search.js
@@ -0,0 +1,208 @@
+var Search =
+{
+ // {{{ properties
+
+ catSelected: false,
+ subCatSelected: false,
+
+ // }}}
+ // {{{ init()
+
+ init: function()
+ {
+ $(".t-list-link").bind("click", function(){
+ var href = $(this).attr('href');
+ $(this).attr('href', href + '&pageOffset=' + window.pageYOffset);
+ });
+
+ $('.search-result-item')
+ .bind('mouseover', Search.highlightMember)
+ .bind('mouseout', Search.lowlightMember)
+ .bind('click', Search.goToMember);
+
+ $("select[name='category_id']")
+ .bind('change', Search.populateMemberSubType);
+ $("select[name='city_id']")
+ .bind('change', Search.repopulateCategories);
+
+ Search.setGET();
+ if (window.location.GET["_qf__SearchForm"] == '') {
+ Search.repopulateCategories();
+ Search.populateMemberSubType();
+ }
+ },
+
+ // }}}
+ // {{{ setGET()
+
+ setGET: function()
+ {
+ var get=(""+location.search).substring(1).split("&");
+ window.location.GET = new Array();
+ for (var i in get) {
+ var temp = get[i].split("=");
+ window.location.GET[temp[0]]=temp.splice(1, temp.length-1).join("=");
+ }
+ },
+
+ // }}}
+ // {{{ highlightMember()
+
+ highlightMember: function(event)
+ {
+ if ($(this).find("a[title='More Info']").length) {
+ $(this).addClass('search-result-item-on');
+ }
+ },
+
+ // }}}
+ // {{{ lowlightMember()
+
+ lowlightMember: function(event)
+ {
+ if ($(this).find("a[title='More Info']").length) {
+ $(this).removeClass('search-result-item-on');
+ }
+ },
+
+ // }}}
+ // {{{ goToMember()
+
+ goToMember: function(event)
+ {
+ if ($(this).find("a[title='More Info']").length) {
+ var link = $(this).find("a[title='More Info']");
+ document.location.href = link.attr('href');
+ }
+ },
+
+ // }}}
+ // {{{ repopulateCategories()
+
+ /**
+ * repopulate the sub category box based on the the value
+ * selected in the city box
+ *
+ * if no city was selected, then get all main categories available
+ *
+ * if a city was selected, then get all main categories available in that
+ * city.
+ */
+ repopulateCategories: function(event)
+ {
+ var city = $("select[name='city_id'] option:selected").val();
+
+ $("select[name='category_id'], select[name='sub_category_id']")
+ .empty()
+ .append('');
+
+ if (city == '') {
+ var usedValues = Array();
+ jQuery.each(CityCats, function(id, obj) {
+ if (CityCats[id]) {
+ jQuery.each(CityCats[id], function(i, j) {
+ if (!usedValues[i]) {
+ usedValues[i] = true;
+ var cat = mainCats[i];
+ $("select[name='category_id']")
+ .append('');
+ }
+ });
+ }
+ });
+ } else {
+ jQuery.each(CityCats[city], function(id, obj) {
+ if (CityCats[city]) {
+ var cat = mainCats[id];
+ $("select[name='category_id']")
+ .append('');
+ }
+ });
+ }
+
+ // If only one option is available, default to have it selected.
+ if ($("select[name='category_id'] option").length == 2) {
+ $("select[name='category_id'] option:last-child")
+ .attr('selected', 'selected');
+ // need to repopulate the sub cats, b/c we already know what
+ // the selected cat is.
+ Search.populateMemberSubType(false);
+ }
+
+ // Figure out wich category we need to set as the selected value
+ var category_id = window.location.GET['category_id'];
+ if (parseInt(category_id) != 'NaN') {
+ if (!Search.catSelected) {
+ Search.catSelected = true;
+ $("select[name='category_id'] option[value='"+category_id+"']").attr('selected', 'selected');
+ }
+ }
+ },
+
+ // }}}
+ // {{{ populateMemberSubType()
+
+ /**
+ * repopulate the sub category box based on the the value
+ * selected in the main category box
+ *
+ * if no city was selected, then get all sub categories available
+ * under the main category selected
+ *
+ * if a city was selected, then get all sub categories available in that
+ * city under the main category selected.
+ */
+ populateMemberSubType: function(event)
+ {
+ var city = $("select[name='city_id'] option:selected").val();
+ var cat = $("select[name='category_id'] option:selected").val();
+
+ $("select[name='sub_category_id']")
+ .empty()
+ .append('');
+
+ var usedValues = Array();
+ if (city == '') {
+ jQuery.each(CityCats, function(id, obj) {
+ if (CityCats[id][cat]) {
+ jQuery.each(CityCats[id][cat], function(i, j) {
+ if (!usedValues[i]) {
+ usedValues[i] = true;
+ $("select[name='sub_category_id']")
+ .append('');
+ }
+ });
+ }
+ });
+ } else {
+ jQuery.each(CityCats[city], function(key, obj) {
+ jQuery.each(CityCats[city][cat], function(i, j) {
+ if (!usedValues[i]) {
+ usedValues[i] = true;
+ $("select[name='sub_category_id']")
+ .append('');
+ }
+ });
+ });
+ }
+
+ // If only one option is available, default to have it selected.
+ if ($("select[name='sub_category_id'] option").length == 2) {
+ $("select[name='sub_category_id'] option:last-child")
+ .attr('selected', 'selected');
+ }
+
+ // Figure out wich sub category we need to set as the selected value
+ var sub_category_id = window.location.GET['sub_category_id'];
+ if (parseInt(sub_category_id) != 'NaN') {
+ if (!Search.subCatSelected && event != false) {
+ Search.subCatSelected = true;
+ $("select[name='sub_category_id'] option[value='"+sub_category_id+"']").attr('selected', 'selected');
+ }
+ }
+ }
+
+ // }}}
+};
+
+$(document).ready(Search.init);
diff --git a/Toolkit/Members/libjs/edit-amenity.js b/Toolkit/Members/libjs/edit-amenity.js
new file mode 100644
index 0000000..6aa77e4
--- /dev/null
+++ b/Toolkit/Members/libjs/edit-amenity.js
@@ -0,0 +1,19 @@
+/**
+ * When we are adding an amenity we want to focus on the first text field
+ * of the form.
+ */
+var MemberAmenity =
+{
+ init: function()
+ {
+ // Find a member id in the search params, this will let us know we
+ // are editing a member and then we don't want to focus on the
+ // the first field.
+ var idRegExp = /.*(\?|&)id=\d+.*$/g;
+ if (!idRegExp.test(location.search)) {
+ $('form :input:text:visible:enabled:first').focus();
+ }
+ }
+}
+
+$(document).ready(MemberAmenity.init);
diff --git a/Toolkit/Members/libjs/edit-category.js b/Toolkit/Members/libjs/edit-category.js
new file mode 100644
index 0000000..5a3a83b
--- /dev/null
+++ b/Toolkit/Members/libjs/edit-category.js
@@ -0,0 +1,19 @@
+/**
+ * When we are adding a category we want to focus on the first text field
+ * of the form.
+ */
+var MemberCategory =
+{
+ init: function()
+ {
+ // Find a member id in the search params, this will let us know we
+ // are editing a member and then we don't want to focus on the
+ // the first field.
+ var idRegExp = /.*(\?|&)id=\d+.*$/g;
+ if (!idRegExp.test(location.search)) {
+ $('form :input:text:visible:enabled:first').focus();
+ }
+ }
+}
+
+$(document).ready(MemberCategory.init);
diff --git a/Toolkit/Members/libjs/edit-city.js b/Toolkit/Members/libjs/edit-city.js
new file mode 100644
index 0000000..98c9fc9
--- /dev/null
+++ b/Toolkit/Members/libjs/edit-city.js
@@ -0,0 +1,43 @@
+/**
+ * When adding a city, set the focus to the first text field in the form
+ * after the page loads.
+ *
+ * setup the fckeditor for the textarea fields
+ */
+var MemberCity =
+{
+ baseUrl: null,
+
+ init: function()
+ {
+ // Find a member id in the search params, this will let us know we
+ // are editing a member and then we don't want to focus on the
+ // the first field.
+ var idRegExp = /.*(\?|&)id=\d+.*$/g;
+ if (!idRegExp.test(location.search)) {
+ $(":text:visible:enabled:first").focus();
+ }
+
+ MemberCity.baseUrl = location.protocol + '//' + location.hostname + '/';
+
+ var url = location.pathname;
+ if (location.hostname == 'devsys2.gaslightmedia.com') {
+ var urlParts = url.split('/');
+ MemberCity.baseUrl += urlParts[1] + '/';
+ } else if (location.hostname == 'kanga.acrewoods.com') {
+ var site = location.pathname.split('/');
+ var urlParts = url.split('/');
+ MemberCity.baseUrl += urlParts[1] + '/' + site[2] + '/';
+ }
+ if ($('#description')) {
+ var oFCKeditor = new FCKeditor('description');
+ oFCKeditor.BasePath = MemberCity.baseUrl + 'fckeditor/';
+ oFCKeditor.ToolbarSet = 'LimitedToolset';
+ oFCKeditor.Width = 367;
+ oFCKeditor.Height = 250;
+ oFCKeditor.ReplaceTextarea();
+ }
+ }
+}
+
+$(document).ready(MemberCity.init);
\ No newline at end of file
diff --git a/Toolkit/Members/libjs/edit-html-email.js b/Toolkit/Members/libjs/edit-html-email.js
new file mode 100644
index 0000000..ff921eb
--- /dev/null
+++ b/Toolkit/Members/libjs/edit-html-email.js
@@ -0,0 +1,47 @@
+/**
+ * When adding a city, set the focus to the first text field in the form
+ * after the page loads.
+ *
+ * setup the fckeditor for the textarea fields
+ */
+var HtmlEmail =
+{
+ baseUrl: null,
+
+ init: function()
+ {
+ // Find a member id in the search params, this will let us know we
+ // are editing a member and then we don't want to focus on the
+ // the first field.
+ var idRegExp = /.*(\?|&)id=\d+.*$/g;
+ if (!idRegExp.test(location.search)) {
+ $(":text:visible:enabled:first").focus();
+ }
+
+ HtmlEmail.baseUrl = location.protocol + '//' + location.hostname + '/';
+
+ var url = location.pathname;
+ if (location.hostname == 'devsys2.gaslightmedia.com') {
+ var urlParts = url.split('/');
+ HtmlEmail.baseUrl += urlParts[1] + '/';
+ } else if (location.hostname == 'steve.gaslightmedia.com') {
+ var site = location.pathname.split('/');
+ var urlParts = url.split('/');
+ HtmlEmail.baseUrl += urlParts[1] + '/' + site[2] + '/';
+ } else if (location.hostname == 'kanga.acrewoods.com') {
+ var site = location.pathname.split('/');
+ var urlParts = url.split('/');
+ HtmlEmail.baseUrl += urlParts[1] + '/' + site[2] + '/';
+ }
+ if ($('#response')) {
+ var oFCKeditor = new FCKeditor('response');
+ oFCKeditor.BasePath = HtmlEmail.baseUrl + 'fckeditor/';
+ oFCKeditor.ToolbarSet = 'Default';
+ oFCKeditor.Width = 600;
+ oFCKeditor.Height = 500;
+ oFCKeditor.ReplaceTextarea();
+ }
+ }
+}
+
+$(document).ready(HtmlEmail.init);
diff --git a/Toolkit/Members/libjs/edit-member-amenities.js b/Toolkit/Members/libjs/edit-member-amenities.js
new file mode 100644
index 0000000..f696ac5
--- /dev/null
+++ b/Toolkit/Members/libjs/edit-member-amenities.js
@@ -0,0 +1,21 @@
+var MemberAmenity =
+{
+ init: function()
+ {
+ $('label').each(function() {
+ $(this).hover(MemberAmenity.highlight, MemberAmenity.lowlight);
+ });
+ },
+
+ highlight: function(event)
+ {
+ $(this).addClass('amenityOn');
+ },
+
+ lowlight: function(event)
+ {
+ $(this).removeClass('amenityOn');
+ }
+}
+
+$(document).ready(MemberAmenity.init);
diff --git a/Toolkit/Members/libjs/edit-member-contacts.js b/Toolkit/Members/libjs/edit-member-contacts.js
new file mode 100644
index 0000000..fdafd2b
--- /dev/null
+++ b/Toolkit/Members/libjs/edit-member-contacts.js
@@ -0,0 +1,67 @@
+var MemberContacts=
+{
+ baseUrl: null,
+
+ init: function()
+ {
+
+ MemberContacts.baseUrl = location.protocol + '//' + location.hostname + '/';
+
+ var url = location.pathname;
+ if (location.hostname == 'devsys2.gaslightmedia.com') {
+ var urlParts = url.split('/');
+ MemberContacts.baseUrl += urlParts[1] + '/';
+ } else if (location.hostname == 'kanga.acrewoods.com') {
+ var site = location.pathname.split('/');
+ var urlParts = url.split('/');
+ MemberContacts.baseUrl += urlParts[1] + '/' + site[2] + '/';
+ }
+ $('.remove').each(function() {
+ $(this).click(MemberContacts.remove);
+ $(this).hover(MemberContacts.click, MemberContacts.release);
+ });
+
+ $('.contactList').each(function() {
+ $(this).hover(MemberContacts.mouseOn, MemberContacts.mouseOff);
+ $(this).click(MemberContacts.goToContact);
+ });
+ },
+
+ mouseOn: function(event)
+ {
+ $(this).addClass('contactListOn');
+ },
+
+ mouseOff: function(event)
+ {
+ $(this).removeClass('contactListOn');
+ },
+
+ goToContact: function(event)
+ {
+ document.location.href = $(this).find('h3 a').attr('href');
+ return false;
+ },
+
+ remove: function(event)
+ {
+ if (!confirm('Are you sure you wish to remove this contact?\nThis is not reversible!')) {
+ event.preventDefault();
+ }
+ // Don't propagate so we won't go into the member record
+ event.stopImmediatePropagation();
+ },
+
+ click: function(event)
+ {
+ $(this).children().attr('src', MemberContacts.baseUrl + 'assets/remove_clicked.png');
+ },
+
+ release: function(event)
+ {
+ $(this).children().attr('src', MemberContacts.baseUrl + 'assets/remove.png');
+ }
+
+}
+
+$(document).ready(MemberContacts.init);
diff --git a/Toolkit/Members/libjs/edit-member-files.js b/Toolkit/Members/libjs/edit-member-files.js
new file mode 100644
index 0000000..87086e5
--- /dev/null
+++ b/Toolkit/Members/libjs/edit-member-files.js
@@ -0,0 +1,18 @@
+var MemberFiles =
+{
+ init: function()
+ {
+ $('.fileDelete').each(function() {
+ $(this).click(MemberFiles.remove);
+ });
+ },
+
+ remove: function(event)
+ {
+ if (!confirm('Are you sure you wish to remove this file?\nThis is not reversible!')) {
+ event.preventDefault();
+ }
+ }
+}
+
+$(document).ready(MemberFiles.init);
diff --git a/Toolkit/Members/libjs/edit-member-packages.js b/Toolkit/Members/libjs/edit-member-packages.js
new file mode 100755
index 0000000..8f22e5e
--- /dev/null
+++ b/Toolkit/Members/libjs/edit-member-packages.js
@@ -0,0 +1,39 @@
+var MemberPackages =
+{
+ baseUrl: null,
+
+ init: function()
+ {
+ MemberPackages.baseUrl = location.protocol + '//' + location.hostname + '/';
+
+ var url = location.pathname;
+ if (location.hostname == 'devsys2.gaslightmedia.com') {
+ var urlParts = url.split('/');
+ MemberPackages.baseUrl += urlParts[1] + '/';
+ } else if (location.hostname == 'kanga.acrewoods.com') {
+ var site = location.pathname.split('/');
+ var urlParts = url.split('/');
+ MemberPackages.baseUrl += urlParts[1] + '/' + site[2] + '/';
+ }
+
+ if ($('spdescription')) {
+ var oFCKeditor = new FCKeditor('spdescription');
+ oFCKeditor.BasePath = MemberPackages.baseUrl + 'fckeditor/';
+ oFCKeditor.ToolbarSet = 'LimitedToolset';
+ oFCKeditor.Width = 367;
+ oFCKeditor.Height = 250;
+ oFCKeditor.ReplaceTextarea();
+ }
+
+ if ($('gdescription')) {
+ var oFCKeditor = new FCKeditor('gdescription');
+ oFCKeditor.BasePath = MemberPackages.baseUrl + 'fckeditor/';
+ oFCKeditor.ToolbarSet = 'LimitedToolset';
+ oFCKeditor.Width = 367;
+ oFCKeditor.Height = 250;
+ oFCKeditor.ReplaceTextarea();
+ }
+ }
+}
+
+Event.observe(window, 'load', MemberPackages.init);
diff --git a/Toolkit/Members/libjs/edit-member-photos.js b/Toolkit/Members/libjs/edit-member-photos.js
new file mode 100755
index 0000000..7382937
--- /dev/null
+++ b/Toolkit/Members/libjs/edit-member-photos.js
@@ -0,0 +1,78 @@
+var MemberPhotos =
+{
+ baseUrl: null,
+
+ init: function()
+ {
+ $('.photoDelete').click(MemberPhotos.remove);
+
+ // Get the url we are dealing w/.
+ MemberPhotos.baseUrl = location.protocol + '//' + location.hostname + '/';
+
+ var url = location.pathname;
+ if (location.hostname == 'devsys2.gaslightmedia.com') {
+ var urlParts = url.split('/');
+ MemberPhotos.baseUrl += urlParts[1] + '/';
+ } else if (location.hostname == 'kanga.acrewoods.com') {
+ var site = location.pathname.split('/');
+ var urlParts = url.split('/');
+ MemberPhotos.baseUrl += urlParts[1] + '/' + site[2] + '/';
+ }
+
+ // Make just the photos uploaded have an additional class
+ // on them, so we can make them movable later.
+ $(".photoItem:not(.photoUploadForm)").addClass('movable');
+
+ // Update the text on the update button.
+ // Since they have javascript on, the only update
+ // they will actually do on the form is the caption.
+ // They won't be updating the position through the select list.
+ $(":submit[name='update']").val('Update Caption Text');
+
+ // Remove all the positioning select elemnts
+ // so they can't override any new position adjustments
+ // done through drag and drop.
+ $('.position').remove();
+
+ // Add a message for users to tell them how to
+ // reposition thier images.
+ $('#photoList').before('
Click and drag images to reorder positions. Image positions are saved when the fields flash yellow
');
+
+ $('div.container').sortable({
+ placeholder: 'ui-state-highlight',
+ handle: 'img.thumb',
+ opacity: 0.6,
+ revert: true,
+ scroll: true,
+ tolerance: 'pointer',
+ zIndex: 5,
+// containment: 'parent',
+ axis: 'y',
+ cursor: 'n-resize',
+ update: MemberPhotos.updatePos
+ });
+ $('img.thumb').disableSelection();
+ },
+
+ updatePos: function(event, ui)
+ {
+ // Update the photo positions through AJAX.
+ $.ajax({
+ type: 'GET',
+ url: MemberPhotos.baseUrl + 'Toolkit/Members/sortPhotos.php',
+ data: $(this).sortable('serialize'),
+ success: function(transport) {
+ $('.movable').effect('highlight', {}, 700);
+ }
+ });
+ },
+
+ remove: function(event)
+ {
+ if (!confirm('Are you sure you wish to remove this photo?\nThis is not reversible!')) {
+ event.preventDefault();
+ }
+ }
+};
+
+$(document).ready(MemberPhotos.init);
diff --git a/Toolkit/Members/libjs/edit-member.js b/Toolkit/Members/libjs/edit-member.js
new file mode 100755
index 0000000..6e4b8b5
--- /dev/null
+++ b/Toolkit/Members/libjs/edit-member.js
@@ -0,0 +1,95 @@
+var Member =
+{
+ baseUrl: null,
+ categorySelectList: null,
+
+ init: function()
+ {
+ // Find a member id in the search params, this will let us know we
+ // are editing a member and then we don't want to focus on the
+ // the first field.
+ var idRegExp = /.*(\?|&)id=\d+.*$/g;
+ if (!idRegExp.test(location.search)) {
+ $('form :input:text:visible:enabled:first').focus();
+ }
+
+ Member.baseUrl = location.protocol + '//' + location.hostname + '/';
+
+ var url = location.pathname;
+ if (location.hostname == 'devsys2.gaslightmedia.com') {
+ var urlParts = url.split('/');
+ Member.baseUrl += urlParts[1] + '/';
+ } else if (location.hostname == 'kanga.acrewoods.com') {
+ var site = location.pathname.split('/');
+ var urlParts = url.split('/');
+ Member.baseUrl += urlParts[1] + '/' + site[2] + '/';
+ }
+
+ var meals = ['breakfast', 'brunch', 'lunch', 'dinner'];
+ jQuery.each(meals, function(i, j) {
+ $('#edit_member input[name='+j+']:checkbox').click(Member.toggleMealView);
+ $('#edit_member input[name='+j+']:checkbox:not(:checked)').parents('tr').next().toggle().next().toggle();
+ });
+
+ $('.tooltip').cluetip({
+ // character to split title text from body text
+ splitTitle: '`',
+ // show arrow on cluetip
+ arrows: true,
+ // hide cluetip on mouseout
+ mouseOutClose: true,
+ // track mouse movements
+ tracking: true,
+ // keep z index above all other elements on the page
+ cluezIndex: 10000,
+ // effect to open cluetip with
+ fx: {open: 'fadeIn'}
+ });
+
+ if (Member.categorySelectList = $('#categories')) {
+ Member.categorySelectList.after('');
+ $('#addCat').click(Member.addCategory);
+ }
+
+ if ($('#description')) {
+ var oFCKeditor = new FCKeditor('description');
+ oFCKeditor.BasePath = Member.baseUrl + 'fckeditor/';
+ oFCKeditor.ToolbarSet = 'LimitedToolset';
+ oFCKeditor.ReplaceTextarea();
+ }
+ },
+
+ addCategory: function(event)
+ {
+ // Don't allow insertion of the -- Choose Category -- option.
+ if (Member.categorySelectList.get(0).selectedIndex == 0) {
+ return;
+ }
+ var catid = Member.categorySelectList.get(0).value;
+ $('#edit_member').prepend('');
+
+ var index = Member.categorySelectList.get(0).selectedIndex;
+ var category = Member.categorySelectList.get(0).options[index].innerHTML;
+ var d = new Date();
+ var id = d.getTime()
+ var i = '' +
+ category + '';
+ $(this).parents('i').before(i);
+ Member.categorySelectList.get(0).selectedIndex = 0;
+ },
+
+ removeCategory: function(event)
+ {
+ event.stop();
+ $('catid' + this.readAttribute('rel')).remove();
+ this.up().remove();
+ },
+
+ toggleMealView: function(event)
+ {
+ $(this).parents('tr').next().toggle().next().toggle();
+ }
+};
+
+$(document).ready(Member.init);
diff --git a/Toolkit/Members/libjs/edit-region.js b/Toolkit/Members/libjs/edit-region.js
new file mode 100644
index 0000000..5c7f59a
--- /dev/null
+++ b/Toolkit/Members/libjs/edit-region.js
@@ -0,0 +1,19 @@
+/**
+ * When we are adding an region we want to focus on the first text field
+ * of the form.
+ */
+var MemberRegion =
+{
+ init: function()
+ {
+ // Find a member id in the search params, this will let us know we
+ // are editing a member and then we don't want to focus on the
+ // the first field.
+ var idRegExp = /.*(\?|&)id=\d+.*$/g;
+ if (!idRegExp.test(location.search)) {
+ $('form :input:text:visible:enabled:first').focus();
+ }
+ }
+}
+
+$(document).ready(MemberRegion.init);
diff --git a/Toolkit/Members/libjs/list-categories.js b/Toolkit/Members/libjs/list-categories.js
new file mode 100644
index 0000000..97e3bb8
--- /dev/null
+++ b/Toolkit/Members/libjs/list-categories.js
@@ -0,0 +1,50 @@
+var Tree =
+{
+ init: function()
+ {
+ Tree.insertGlobalFunctions();
+
+ tree1 = new tree_component();
+ tree1.init($("#categoryTree"), {
+ cookies : {
+ prefix : "tree1",
+ opts : { path : '/' }
+ },
+ ui : {
+ animation : 500
+ }
+ });
+
+ $('#categoryTree a').bind('click', Tree.editNode);
+ },
+
+ insertGlobalFunctions: function()
+ {
+ $('#categoryTree').before('
' +
+ '' +
+ '' +
+ '
');
+
+ $('.expandAll').bind('click', Tree.expandAll);
+ $('.collapseAll').bind('click', Tree.collapseAll);
+ },
+
+ expandAll: function(event)
+ {
+ $('li.closed').toggleClass('open');
+ $('li.closed').toggleClass('closed');
+ },
+
+ collapseAll: function (event)
+ {
+ $('li.open').toggleClass('closed');
+ $('li.open').toggleClass('open');
+ },
+
+ editNode: function(event)
+ {
+ location.href = $(this).attr('href');
+ }
+};
+
+$(document).ready(Tree.init);
diff --git a/Toolkit/Members/libjs/member-list.js b/Toolkit/Members/libjs/member-list.js
new file mode 100644
index 0000000..76d727d
--- /dev/null
+++ b/Toolkit/Members/libjs/member-list.js
@@ -0,0 +1,76 @@
+var MemberList =
+{
+ baseUrl: null,
+
+ init: function()
+ {
+ $('.searchResult').each(function() {
+ $(this).hover(MemberList.mouseOn, MemberList.mouseOff);
+ $(this).click(MemberList.goToMember);
+ });
+
+ $('.remove').each(function() {
+ $(this).click(MemberList.remove);
+ $(this).hover(MemberList.click, MemberList.release);
+ });
+
+ MemberList.baseUrl = location.protocol + '//' + location.hostname + '/';
+
+ var url = location.pathname;
+ if (location.hostname == 'devsys2.gaslightmedia.com') {
+ var urlParts = url.split('/');
+ MemberList.baseUrl += urlParts[1] + '/';
+ } else if (location.hostname == 'kanga.acrewoods.com') {
+ var site = location.pathname.split('/');
+ var urlParts = url.split('/');
+ MemberList.baseUrl += urlParts[1] + '/' + site[2] + '/';
+ }
+
+ $('#record_search').after('Advanced Search');
+ $('#advanced_search').click(MemberList.toggleAdvancedSearch);
+ $('#advanced_search').trigger('click');
+ },
+
+ toggleAdvancedSearch: function(event)
+ {
+ event.preventDefault();
+ $('#record_search tr').slice(4,8).toggle();
+ },
+
+ mouseOn: function(event)
+ {
+ $(this).addClass('searchResultOn');
+ },
+
+ mouseOff: function(event)
+ {
+ $(this).removeClass('searchResultOn');
+ },
+
+ goToMember: function(event)
+ {
+ document.location.href = $(this).find('h3 a').attr('href');
+ return false;
+ },
+
+ remove: function(event)
+ {
+ if (!confirm('Are you sure you wish to remove this business?\nThis is not reversible!')) {
+ event.preventDefault();
+ }
+ // Don't propagate so we won't go into the member record
+ event.stopImmediatePropagation();
+ },
+
+ click: function(event)
+ {
+ $(this).children().attr('src', MemberList.baseUrl + 'assets/remove_clicked.png');
+ },
+
+ release: function(event)
+ {
+ $(this).children().attr('src', MemberList.baseUrl + 'assets/remove.png');
+ }
+};
+
+$(document).ready(MemberList.init);
diff --git a/Toolkit/Members/libjs/member-pending-list.js b/Toolkit/Members/libjs/member-pending-list.js
new file mode 100644
index 0000000..2f0789a
--- /dev/null
+++ b/Toolkit/Members/libjs/member-pending-list.js
@@ -0,0 +1,42 @@
+var MemberPendingList =
+{
+ baseUrl : null,
+
+ init: function()
+ {
+ $('.searchResult').each(function() {
+ $(this).hover(MemberPendingList.mouseOn, MemberPendingList.mouseOff);
+ $(this).click(MemberPendingList.goToMember);
+ });
+
+ MemberPendingList.baseUrl = location.protocol + '//' + location.hostname + '/';
+
+ var url = location.pathname;
+ if (location.hostname == 'devsys2.gaslightmedia.com') {
+ var urlParts = url.split('/');
+ MemberPendingList.baseUrl += urlParts[1] + '/';
+ } else if (location.hostname == 'kanga.acrewoods.com') {
+ var site = location.pathname.split('/');
+ var urlParts = url.split('/');
+ MemberPendingList.baseUrl += urlParts[1] + '/' + site[2] + '/';
+ }
+ },
+
+ mouseOn: function(event)
+ {
+ $(this).addClass('searchResultOn');
+ },
+
+ mouseOff: function(event)
+ {
+ $(this).removeClass('searchResultOn');
+ },
+
+ goToMember: function(event)
+ {
+ document.location.href = $(this).find('h3 a').attr('href');
+ return false;
+ }
+}
+
+$(document).ready(MemberPendingList.init);
diff --git a/Toolkit/Members/memberClickThru.php b/Toolkit/Members/memberClickThru.php
new file mode 100644
index 0000000..7b9f5d7
--- /dev/null
+++ b/Toolkit/Members/memberClickThru.php
@@ -0,0 +1,29 @@
+
+ * @copyright 2009 Gaslight Media
+ * @license Gaslight Media
+ * @version CVS: $Id: memberClickThru.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link <>
+ */
+
+$dont_include_functions = true;
+/**
+ * Description for require_once
+ */
+require_once '../../setup.phtml';
+if (is_numeric($_GET['member_id'])) {
+ $exposure = new Toolkit_Members_Exposure($_GET['member_id'], 'click');
+}
+if ($_GET['href']) {
+ $href = str_replace("http://", "", $_GET['href']);
+ header("Location: http://" . $href);
+}
+?>
diff --git a/Toolkit/Members/memberFileDownload.php b/Toolkit/Members/memberFileDownload.php
new file mode 100644
index 0000000..a594e26
--- /dev/null
+++ b/Toolkit/Members/memberFileDownload.php
@@ -0,0 +1,32 @@
+
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: memberFileDownload.php,v 1.2 2009/12/15 20:18:15 jamie Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+$dont_include_functions = true;
+
+/**
+ * Description for require_once
+ */
+require_once '../../setup.phtml';
+
+$download = new Toolkit_Members_FileDownload(
+ Toolkit_Database::getInstance()
+);
+$file = $download->getFile($_GET['mid'], $_GET['fid']);
+
+if (!PEAR::isError($file)) {
+ $download->sendFileToBrowser($file);
+} else {
+ exit();
+}
+?>
diff --git a/Toolkit/Members/memberdb-session.sql b/Toolkit/Members/memberdb-session.sql
new file mode 100644
index 0000000..5d159b0
--- /dev/null
+++ b/Toolkit/Members/memberdb-session.sql
@@ -0,0 +1,8 @@
+CREATE TABLE member_session(
+id SERIAL PRIMARY KEY,
+member_id int REFERENCES member ON DELETE CASCADE,
+contact_id int REFERENCES contact ON DELETE CASCADE,
+catid int REFERENCES bus_category ON DELETE CASCADE
+);
+
+GRANT ALL ON member_session to nobody;
diff --git a/Toolkit/Members/memberdb.css b/Toolkit/Members/memberdb.css
new file mode 100644
index 0000000..3ef3869
--- /dev/null
+++ b/Toolkit/Members/memberdb.css
@@ -0,0 +1,410 @@
+/*
+
+h1 {
+ font-size: 16px;
+ }
+#content {
+ margin: 0px;
+}
+#subnavcontainer, #navcontainer,
+#top {
+ margin-right: 0px;
+}
+#wrapper {
+ width: 700px;
+ margin: 0 auto;
+ text-align: left;
+ background: white;
+ padding: 20px;
+ height: 1%;
+ overflow: hidden;
+ }
+Above is only for template , DISREGARD :) */
+#advanced-search {
+ text-align: right;
+ cursor: pointer;
+ color: blue;
+}
+.req {
+ color: red;
+}
+#form-warning-top {
+ color: black;
+ font-size: 110%;
+ font-weight: bold;
+ margin: 10px;
+ padding: 7px;
+ border: 1px solid red;
+ background-color: #FFCCCC;
+}
+#form-success-top {
+ color: black;
+ font-size: 110%;
+ font-weight: bold;
+ margin: 10px;
+ padding: 7px;
+ border: 1px solid green;
+ background-color: #CCFFCC;
+}
+
+img {
+ border: 0;
+ display: block;
+ }
+/* --------------- */
+/* NAVIGATION */
+/* --------------- */
+#nav-detail {
+ margin-top: 12px;
+ height: 1%;
+ overflow: hidden;
+ clear: left;
+ }
+#nav-detail ul {
+ padding: 0px 0;
+ padding-bottom: 3px;
+ margin: 0;
+ margin-top: 10px;
+ border-bottom: 1px solid #666;
+ font-weight: bold;
+}
+#nav-detail ul li {
+ list-style: none;
+ margin: 0;
+ display: inline;
+}
+#nav-detail ul li a {
+ padding: 3px 0.5em;
+ margin-left: 3px;
+ border: 1px solid #666;
+ border-bottom: none;
+ background: #E6EFD1;
+ text-decoration: none;
+}
+#nav-detail ul li a:link { color: #666; }
+#nav-detail ul li a:visited { color: #666; }
+#nav-detail ul li a:hover {
+ color: #666;
+ background: #ccc;
+ background: #FFFBDF;
+ border-color: #666;
+}
+#nav-detail ul li a.current {
+ background: white;
+ border-bottom: 1px solid white;
+ color: #000;
+}
+
+/* Member Box */
+#member-info {
+ margin: 0;
+ border: 1px solid #666;
+ border-top: 0;
+ padding: 10px;
+ position: relative;
+ height: 1%;
+ overflow: hidden;
+ clear: left;
+ }
+
+#mRow1 {
+ float: left;
+ position: relative;
+ margin: 0 0 0 10px;
+ display: inline;
+ width: 380px;
+ }
+#mRow2 {
+ float: right;
+ position: relative;
+ }
+#mRow1 .text {
+ width: 180px;
+ }
+#mRow2 .text {
+ width: 150px;
+ }
+.form {
+ clear: left;
+ display: block;
+ position: relative;
+ margin: 0 0 1em 0;
+ padding: 0;
+ border: 0;
+ }
+/* narrower column */
+.formNarrow {
+ clear: right;
+ margin: 0 0 1em 0;
+ }
+.form legend {
+ font-size: 1.2em;
+ font-weight: bold;
+ margin: 0;
+ padding: 0 0 0.4em 0;
+ color: #000;
+ }
+.form table,
+.form td {
+ border-collapse: collapse;
+ border: 1px solid #fff;
+ padding: 0;
+ background: #D6DFC3;
+ }
+.form td {
+ padding: 4px 6px;
+ }
+.form label {
+ display: block;
+ }
+.labelcell {
+ text-align: right;
+ width: 120px;
+ }
+.formNarrow .labelcell {
+ width: 110px;
+ }
+.fieldcell {
+ text-align: left;
+ width: 220px;
+ }
+.formNarrow .fieldcell {
+ width: 150px;
+ }
+
+/* Multiple rows in one cell */
+.fieldcell i {
+ display: block;
+ font-style: normal;
+ padding: 5px;
+ text-align: left;
+ background-color: #eee;
+ margin-bottom: 1px;
+ }
+.fieldcell i img {
+ margin-right: 6px;}
+
+/* Small graphics */
+.remove {
+ float: right;
+ clear: right;}
+.add {
+ display: block;
+ /* float: right; */
+ display: block;
+ font-style: normal;
+ padding: 5px;
+ text-align: left;
+ background-color: #eee;
+ margin-bottom: 1px;
+ }
+.add img {float: left; margin-right: 10px;}
+.info {
+ float: right;
+ }
+
+.priceFrom,
+.priceTo {
+ width: 4em;
+ }
+.submit {display: block;}
+
+/* Submit */
+.submitArea {
+ background: #D6DFC3;
+ text-align: center;
+ padding: 10px;
+ clear: both;
+ }
+.submitArea input {
+ margin: 0 auto;
+ display: block;
+ }
+
+
+/* --------------- */
+/* PHOTOS */
+/* --------------- */
+.photoItem {
+ margin-top: 1em;
+ padding: 20px;
+ border: 1px solid #ccc;
+ height: 1%;
+ overflow: hidden;
+ position: relative;
+ background: #D6DFC3;
+ }
+.photoItem .thumb {
+ float: left;
+ position: relative;
+ margin-right: 20px;
+ }
+.photoItem i {
+ font-style: normal;
+ font-weight: bold;
+ display: block;
+ }
+.photoItem input {margin-top: 0.5em;}
+.photoItem input.text {
+ width: 400px;
+ display: block;
+ }
+.photoItem .photoDelete {
+/* display: block;
+ margin-top: 1em;
+ border: 1px solid #ccc;
+ background: #FFEFEF;
+ width: 130px;
+ padding: 3px;
+ color: #000;
+*/
+ position: absolute;
+ bottom: 20px;
+ right: 20px;
+
+ }
+.photoDelete:hover {background: #EFD1D1;}
+.photoItem .photoDelete img {
+ float: left;
+ margin-right: 6px;
+ }
+.photoOptions {float: left;}
+
+
+/* --------------- */
+/* PACKAGES */
+/* --------------- */
+
+.packageItem {
+ margin-top: 1em;
+ padding: 20px;
+ border: 1px solid #96A379;
+ height: 1%;
+ overflow: hidden;
+ position: relative;
+ background: #D6DFC3;
+ }
+
+.packageItem .thumb {
+ position: relative;
+ margin-bottom: 1em;
+ }
+.packageText {
+ float: left;
+ width: 350px;
+ padding-bottom: 1em;
+ }
+.packageItem i {
+ font-style: normal;
+ font-weight: bold;
+ display: block;
+ padding-top: 1em;
+
+ }
+.packageItem input {margin-top: 0.5em;}
+.packageItem input.text {
+ width: 200px;
+ display: block;
+ }
+.packageItem textarea {
+ width: 300px;
+ height: 150px;
+ }
+.packageItem .packageDelete {
+ display: block;
+ margin-top: 1em;
+ border: 1px solid #ccc;
+ background: #FFEFEF;
+ width: 140px;
+ padding: 3px;
+ position: absolute;
+ bottom: 20px;
+ right: 20px;
+ color: #000;
+ }
+.packageDelete:hover {background: #EFD1D1;}
+.packageItem .packageDelete img {
+ float: left;
+ margin-right: 6px;
+ }
+.packageOptions {float: left;}
+
+
+
+/* --------------- */
+/* AMENITIES */
+/* --------------- */
+.amenityList {
+ list-style-type: none;
+ float: left;
+ position: relative;
+ margin-right: 50px;
+ zoom: 1;
+ width: 200px;
+ }
+.amenityList input {
+ /* No Luck, see http://meyerweb.com/eric/thoughts/2007/05/15/formal-weirdness/ */
+}
+.amenityList li {
+ vertical-align: middle;
+ height: 1%;
+ overflow: hidden;
+ font-size: 1.2em;
+ }
+.amenityList label {
+ padding: 4px;
+ display: block;
+ background: #D6DFC3;
+ margin-bottom: 1px;
+}
+.amenityList label.amenityOn {
+ background-color: #E6EFD1;
+ cursor: hand;
+ cursor: pointer;
+ }
+
+/* SPECIFIC TO SEARCH RESULT HERE */
+.searchResult {
+ border: 1px solid #96A379;
+ padding: 10px 20px;
+ margin: 5px 0;
+ background-color: #D6DFC3;
+ height: 1%;
+ overflow: hidden;
+ position: relative;
+}
+.searchResultOn {
+ background: url(../../assets/searchResultOn.gif) no-repeat 95% center #E6EFD1;
+ cursor: hand;
+ cursor: pointer;
+}
+.searchResult h3 {
+ font-size: 15px;
+ color: #333;
+ margin: 0;
+ float: left;
+}
+.searchResultOn h3 {
+ color: #000;
+}
+.searchResult .phone {
+ position: absolute;
+ bottom: 10px;
+ right: 300px;
+}
+.searchResult a.email {
+ position: absolute;
+ bottom: 10px;
+ right: 150px;
+}
+.searchResult a {
+ color: #96A379;
+ text-decoration: none;
+}
+.searchResult a.email {
+ text-decoration: underline;
+}
+.searchResult a:link {color: #585F47;}
+.searchResult a:visited {color: #585F47;}
+.searchResult a:hover {color: #585F47;}
+.searchResult a:active {color: #585F47;}
diff --git a/Toolkit/Members/memberdb.sql b/Toolkit/Members/memberdb.sql
new file mode 100644
index 0000000..0374988
--- /dev/null
+++ b/Toolkit/Members/memberdb.sql
@@ -0,0 +1,390 @@
+CREATE TABLE state (
+state_id serial PRIMARY KEY,
+state_name text,
+state_abb varchar(2),
+us_state boolean default false
+);
+
+DELETE FROM state;
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Alabama', 'AL');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Alaska', 'AK');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Arizona', 'AZ');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Arkansas', 'AR');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'California', 'CA');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Colorado', 'CO');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Connecticut', 'CT');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Delaware', 'DE');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'District of Columbia', 'DC');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Florida', 'FL');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Georgia', 'GA');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Hawaii', 'HI');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Idaho', 'ID');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Illinois', 'IL');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Indiana', 'IN');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Iowa', 'IA');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Kansas', 'KS');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Kentucky', 'KY');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Louisiana', 'LA');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Maine', 'ME');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Maryland', 'MD');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Massachusetts', 'MA');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Michigan', 'MI');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Minnesota', 'MN');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Mississppi', 'MS');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Missouri', 'MO');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Montana', 'MT');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Nebraska', 'NE');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Nevada', 'NV');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'New Hampshire', 'NH');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'New Jersey', 'NJ');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'New Mexico', 'NM');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'New York', 'NY');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'North Carolina', 'NC');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'North Dakota', 'ND');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Ohio', 'OH');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Oklahoma', 'OK');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Oregon', 'OR');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Pennsylvania', 'PA');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Rhode Island', 'RI');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'South Carolina', 'SC');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'South Dakota', 'SD');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Tennessee', 'TN');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Texas', 'TX');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Utah', 'UT');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Vermont', 'VT');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Virginia', 'VA');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Washington', 'WA');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'West Virginia', 'WV');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Wisconsin', 'WI');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (true, 'Wyoming', 'WY');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'Alberta', 'AB');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'American Samoa', 'AS');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'British Columbia', 'BC');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'Federated States of Micronesia', 'FM');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'Guam', 'GU');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'Manitoba', 'MB');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'Marshall Islands', 'MH');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'New Brunswick', 'NB');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'Newfoundland', 'NF');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'Northern Mariana Islands', 'MP');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'Northwest Territories', 'NT');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'Nova Scotia', 'NS');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'Ontario', 'ON');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'Palau', 'PW');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'Prince Edward Island', 'PE');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'Puerto Rico', 'PR');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'Quebec', 'QC');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'Saskatchewan', 'SK');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'Virgin Islands', 'VI');
+INSERT INTO state (us_state, state_name, state_abb) VALUES (false, 'Yukon', 'YT');
+
+GRANT ALL ON state_state_id_seq TO nobody;
+GRANT ALL ON state TO nobody;
+
+CREATE TABLE region (
+region_id serial PRIMARY KEY,
+region_name text UNIQUE
+);
+
+DELETE FROM region;
+ALTER SEQUENCE region_region_id_seq RESTART WITH 1;
+INSERT INTO region (region_name) VALUES ('Temp Region');
+
+GRANT ALL ON region_region_id_seq TO nobody;
+GRANT ALL ON region TO nobody;
+
+CREATE TABLE county (
+county_id serial PRIMARY KEY,
+state_id integer REFERENCES state(state_id) ON DELETE CASCADE,
+county_name text,
+region_id integer REFERENCES region(region_id) ON DELETE CASCADE
+);
+
+DELETE FROM county;
+ALTER SEQUENCE county_county_id_seq RESTART WITH 1;
+INSERT INTO county(state_id, county_name, region_id) VALUES (1, 'Temp County', 1);
+
+GRANT ALL ON county_county_id_seq TO nobody;
+GRANT ALL ON county TO nobody;
+
+CREATE TABLE city (
+city_id serial PRIMARY KEY,
+state_id integer REFERENCES state(state_id) ON DELETE CASCADE,
+city_name text,
+county_id integer REFERENCES county(county_id) ON DELETE CASCADE,
+region_id integer REFERENCES region(region_id) ON DELETE CASCADE,
+description text,
+image text
+);
+
+DELETE FROM city;
+ALTER SEQUENCE city_city_id_seq RESTART WITH 1;
+INSERT INTO city (state_id, city_name, county_id, region_id) VALUES (1, 'Temp City', 1, 1);
+
+GRANT ALL ON city_city_id_seq TO nobody;
+GRANT ALL ON city TO nobody;
+
+CREATE TABLE member (
+member_id serial primary key,
+member_name text UNIQUE,
+member_login text UNIQUE,
+member_passwd text,
+street text,
+lat double precision,
+lon double precision,
+country text,
+phone text,
+fax text,
+process_email text,
+url text,
+city text,
+city_id integer references city(city_id) ON DELETE SET NULL,
+state text,
+state_id integer references state(state_id) ON DELETE SET NULL,
+description text,
+create_date date DEFAULT now(),
+zip text,
+toll_free text,
+member_contact_email text,
+spotlight boolean,
+logo text,
+mailing_address text,
+primary_contact text,
+primary_contact_fname text,
+primary_contact_lname text,
+active boolean default false,
+mailing_city text,
+mailing_city_id integer references city(city_id) ON DELETE SET NULL,
+mailing_state_id integer references state(state_id) ON DELETE SET NULL,
+mailing_zip text,
+join_date date
+region integer references region(region_id) ON DELETE SET NULL,
+new_member boolean default false,
+facebook text,
+twitter text,
+myspace text,
+linkedin text,
+blog text
+);
+
+GRANT ALL ON member_member_id_seq TO nobody;
+GRANT ALL ON member TO nobody;
+
+CREATE TABLE member_accommodations (
+id serial PRIMARY KEY,
+reservation_id text,
+num_rooms integer,
+year_round boolean default false,
+member_id integer REFERENCES member(member_id) ON DELETE CASCADE
+);
+
+GRANT ALL ON member_accommodations_id_seq TO nobody;
+GRANT ALL ON member_accommodations TO nobody;
+
+CREATE TABLE amenity (
+amenity_id serial PRIMARY KEY,
+amenity_name text,
+amenity_icon text,
+display_form boolean
+);
+
+GRANT ALL ON amenity_amenity_id_seq TO nobody;
+GRANT ALL ON amenity TO nobody;
+
+CREATE TABLE member_amenity (
+member_amenity_id serial PRIMARY KEY,
+member_id integer REFERENCES member(member_id) ON DELETE CASCADE,
+amenity_id integer REFERENCES amenity(amenity_id) ON DELETE CASCADE
+);
+
+GRANT ALL ON member_amenity_member_amenity_id_seq TO nobody;
+GRANT ALL ON member_amenity TO nobody;
+
+CREATE TABLE category (
+category_id serial PRIMARY KEY,
+name text NOT NULL,
+parent_id integer DEFAULT 0,
+pos integer DEFAULT 1,
+accommodations boolean default false,
+restaurant boolean default false,
+golf boolean default false,
+code integer
+);
+
+DELETE FROM category;
+ALTER SEQUENCE category_category_id_seq RESTART WITH 1;
+INSERT INTO category (name, parent_id, pos, accommodations, restaurant, golf) VALUES ('Parent', 0, 1, true, true, true);
+INSERT INTO category (name, parent_id, pos, accommodations, restaurant, golf) VALUES ('Child', 1, 1, false, false, false);
+INSERT INTO category (name, parent_id, pos, accommodations, restaurant, golf) VALUES ('Sibling', 1, 2, false, true, false);
+INSERT INTO category (name, parent_id, pos, accommodations, restaurant, golf) VALUES ('Grand Child', 2, 1, false, false, true);
+
+GRANT ALL ON category_category_id_seq TO nobody;
+GRANT ALL ON category TO nobody;
+
+CREATE TABLE bus_cat_member(
+id serial PRIMARY KEY,
+catid integer REFERENCES bus_category(id) ON DELETE CASCADE,
+memb_type integer REFERENCES category(id) ON DELETE CASCADE,
+prop_type integer
+);
+
+GRANT ALL on bus_cat_member_id_seq to nobody;
+GRANT ALL on bus_cat_member to nobody;
+CREATE UNIQUE INDEX bus_cat_member_id_index on bus_cat_member (id);
+CREATE INDEX bus_cat_member_catid_memb_index on bus_cat_member (catid, memb_type);
+
+CREATE TABLE member_category (
+member_category_id serial PRIMARY KEY,
+member_id integer REFERENCES member(member_id) ON DELETE CASCADE,
+category_id integer REFERENCES category(category_id) ON DELETE CASCADE
+);
+
+GRANT ALL ON member_category_member_category_id_seq TO nobody;
+GRANT ALL ON member_category TO nobody;
+
+CREATE TABLE member_ccard_type (
+member_ccard_type_id serial PRIMARY KEY,
+member_id integer REFERENCES member(member_id) ON DELETE CASCADE,
+ccard_type_id integer REFERENCES ccard_type(ccard_type_id) ON DELETE CASCADE
+);
+
+GRANT ALL ON member_ccard_type_member_ccard_type_id_seq TO nobody;
+GRANT ALL ON member_ccard_type TO nobody;
+
+CREATE TABLE member_contacts (
+id serial PRIMARY KEY,
+title text,
+fname text NOT NULL,
+lname text NOT NULL,
+email text,
+phone text,
+send_mail boolean DEFAULT false,
+member_id integer REFERENCES member(member_id) ON DELETE CASCADE
+);
+
+GRANT ALL ON member_contacts_id_seq TO nobody;
+GRANT ALL ON member_contacts TO nobody;
+
+CREATE TABLE member_files (
+id serial PRIMARY KEY,
+file_contents text,
+create_date date DEFAULT now(),
+original_name text NOT NULl,
+size integer NOT NULL,
+file_name text NOT NULL,
+name_on_disk text NOT NULL,
+pending boolean DEFAULT true,
+member_id integer REFERENCES member(member_id) ON DELETE CASCADE
+);
+
+GRANT ALL ON member_files_id_seq TO nobody;
+GRANT ALL ON member_files TO nobody;
+
+CREATE TABLE member_golf (
+id serial PRIMARY KEY,
+par text,
+yardage text,
+course_rating text,
+slope_rating text,
+walking_course boolean DEFAULT false,
+holes18 text,
+holes9 text,
+member_id integer REFERENCES member(member_id) ON DELETE CASCADE
+);
+
+GRANT ALL ON member_golf_id_seq TO nobody;
+GRANT ALL ON member_golf TO nobody;
+
+CREATE TABLE member_packages (
+id serial PRIMARY KEY,
+title text,
+description text,
+image text,
+type text,
+pending boolean DEFAULT true,
+pos integer,
+sdate date,
+edate date,
+member_id integer REFERENCES member(member_id) ON DELETE CASCADE
+);
+
+GRANT ALL ON member_packages_id_seq TO nobody;
+GRANT ALL ON member_packages TO nobody;
+
+CREATE TABLE member_photos (
+id serial PRIMARY KEY,
+image text NOT NULL,
+caption text,
+pending boolean DEFAULT true,
+pos integer DEFAULT 1,
+member_id integer REFERENCES member(member_id) ON DELETE CASCADE
+);
+
+GRANT ALL ON member_photos_id_seq TO nobody;
+GRANT ALL ON member_photos TO nobody;
+
+CREATE TABLE member_restaurants (
+id serial PRIMARY KEY,
+breakfast boolean DEFAULT false,
+breakfast_from text,
+breakfast_to text,
+brunch boolean DEFAULT false,
+brunch_from text,
+brunch_to text,
+lunch boolean DEFAULT false,
+lunch_from text,
+lunch_to text,
+dinner boolean DEFAULT false,
+dinner_from text,
+dinner_to text,
+alcohol boolean DEFAULT false,
+non_smoking boolean DEFAULT false,
+member_id integer REFERENCES member(member_id) ON DELETE CASCADE
+);
+
+GRANT ALL ON member_restaurants_id_seq TO nobody;
+GRANT ALL ON member_restaurants TO nobody;
+
+CREATE TABLE member_updates (
+id serial PRIMARY KEY,
+field text,
+update text,
+alter_time timestamp without time zone DEFAULT now(),
+db_table text NOT NULL,
+data_type text,
+label text,
+foreign_key integer,
+member_id integer REFERENCES member(member_id) ON DELETE CASCADE,
+field_type text
+);
+
+GRANT ALL ON member_updates_id_seq TO nobody;
+GRANT ALL ON member_updates TO nobody;
+
+CREATE TABLE ccard_type (
+ccard_type_id serial PRIMARY KEY,
+ccard_type_name text,
+ccard_type_icon text
+);
+
+DELETE FROM ccard_type;
+ALTER SEQUENCE ccard_type_ccard_type_id_seq RESTART WITH 1;
+INSERT INTO ccard_type(ccard_type_name, ccard_type_icon) VALUES ('Visa', 'cardvisa.gif');
+INSERT INTO ccard_type(ccard_type_name, ccard_type_icon) VALUES ('Master Card', 'cardmaster.gif');
+INSERT INTO ccard_type(ccard_type_name, ccard_type_icon) VALUES ('Discover', 'carddiscover.gif');
+INSERT INTO ccard_type(ccard_type_name, ccard_type_icon) VALUES ('American Express', 'cardamex.gif');
+INSERT INTO ccard_type(ccard_type_name, ccard_type_icon) VALUES ('Dinner', 'carddinner.gif');
+
+GRANT ALL ON ccard_type_ccard_type_id_seq TO nobody;
+GRANT ALL ON ccard_type TO nobody;
+
+CREATE TABLE member_ccard_type (
+member_ccard_type_id serial PRIMARY KEY,
+member_id integer REFERENCES member(member_id) ON DELETE CASCADE,
+ccard_type_id integer REFERENCES ccard_type(ccard_type_id) ON DELETE SET NULL
+);
+
+GRANT ALL ON member_ccard_type_member_ccard_type_id_seq TO nobody;
+GRANT ALL ON member_ccard_type TO nobody;
+
+\i /usr/share/postgresql/8.2/contrib/tablefunc.sql
diff --git a/Toolkit/Members/members.ini b/Toolkit/Members/members.ini
new file mode 100644
index 0000000..176f721
--- /dev/null
+++ b/Toolkit/Members/members.ini
@@ -0,0 +1,47 @@
+; Member Database configuration file
+[conf]
+; Allow members to have their own coupons.
+coupons = On
+; Allow regions in the application.
+regions = On
+; Only allow cities in member records that are added by an admin user.
+; Turning on will provide admin with an extra form that will allow them
+; to add/edit/remove cities.
+; Turning off will allow any city name to be entered when editing member
+; records.
+controlledCities = On
+amenities = On
+counties = Off
+newMemberRequests = On
+; Determines if member changes must be first approved by admin
+; before they will be written to their actual record.
+strictPending = Off
+; Allow duplicate member names in the database
+duplicateMembers = Off
+
+[photos]
+; Maximum number of photos a member is allowed to upload per record
+maxPhotos = 100
+; Maximum length allowed in text fields for photo captions
+maxCaptionLength = 60
+; This is the template when editing / adding photos to a members gallery
+; Not to be confused w/ the templates for the add / edit photo forms.
+editGalleryTemplate = "editPhotoGallery.tpl"
+
+; How the app should be displayed (Business, Members, Users, etc...)
+; [List Businesses] [Add Business Listing] [Pending Business Listing Update]
+; [List Members] [Add Member Listing] [Pending Member Listing Update]
+[listing type]
+singular = "Member"
+plural = "Members"
+
+; How the regions should be displayed (Regions, Counties, Areas, etc...)
+; [Regions] [List Regions] [Add Regions]
+; [Counties] [List Counties] [Add Counties]
+[region type]
+singular = "Regions"
+plural = "Region"
+
+[tables]
+pendingTable = "member_updates"
+photosTable = "member_photos"
diff --git a/Toolkit/Members/sortPhotos.php b/Toolkit/Members/sortPhotos.php
new file mode 100644
index 0000000..0939dd1
--- /dev/null
+++ b/Toolkit/Members/sortPhotos.php
@@ -0,0 +1,54 @@
+
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: sortPhotos.php,v 1.1.1.1 2009/09/17 20:08:56 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+require_once '../../setup.phtml';
+// Make sure the users browser doesn't cache the result.
+
+// Time in the past.
+header('Expires: Wed, 23 Dec 1980 00:30::00 GMT');
+header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
+header('Cache-Control: no-cache, must-revalidate');
+header('Pragma: no-cache');
+
+if (!is_array($_GET['photos'])) {
+ return;
+}
+$newOrder = $_GET['photos'];
+
+try {
+ $dbh->beginTransaction();
+
+ $sql = "
+ UPDATE member_photos
+ SET pos = :pos
+ WHERE id = :id";
+ $stmt = $dbh->prepare($sql);
+ foreach ($newOrder as $k => &$v) {
+ $pos = $k + 1;
+ $stmt->bindParam(':pos', $pos, PDO::PARAM_INT);
+ $stmt->bindParam(':id', $v, PDO::PARAM_INT);
+ $stmt->execute();
+ }
+ $dbh->commit();
+ echo true;
+} catch (PDOException $e) {
+ $dbh->rollBack();
+ echo 'PDO Exception Caught. ';
+ echo 'Error with the database: ';
+ echo 'Error: ' . $e->getMessage() . ' ';
+ echo 'File: ' . $e->getFile() . ' ';
+ echo 'Line: ' . $e->getLine() . ' ';
+ print_r($dbh->errorInfo());
+}
+?>
diff --git a/Toolkit/Members/templates/addPackage.tpl b/Toolkit/Members/templates/addPackage.tpl
new file mode 100644
index 0000000..aa40473
--- /dev/null
+++ b/Toolkit/Members/templates/addPackage.tpl
@@ -0,0 +1,41 @@
+
diff --git a/Toolkit/Membersonly.php b/Toolkit/Membersonly.php
new file mode 100644
index 0000000..4844e45
--- /dev/null
+++ b/Toolkit/Membersonly.php
@@ -0,0 +1,337 @@
+
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: Membersonly.php,v 1.2 2009/12/15 20:18:15 jamie Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Base class for the memberdb
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Membersonly
+{
+ // {{{ properties
+
+ /**
+ * Strict pending for member updates
+ */
+ const STRICT_PENDING = true;
+
+ /**
+ * Table that holds the member update requests
+ */
+ const PENDING_TABLE = 'member_updates';
+
+ // }}}
+
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * @access public
+ */
+ public function __construct()
+ {
+ }
+
+ // }}}
+
+ // {{{ toHtml()
+
+ /**
+ * Determine which form to show to the user
+ *
+ * When editing a member the (a)ction in the URL controls
+ * which form is displayed to the user. Member Id's from
+ * the database should be passed along as the ID in the $_GET array.
+ *
+ * @return void
+ * @access public
+ */
+ public function toHtml()
+ {
+ $mid = $GLOBALS['memberAuth']->getAuthData('member_id');
+ // application configuration
+ $conf = new Config;
+ $root =& $conf->parseConfig(BASE . 'Toolkit/Members/members.ini', 'IniFile');
+
+ $nav =& new Toolkit_Members_RecordNavigation($root);
+ $nav->setupUserNavStructure();
+
+ $tplOpts = Toolkit_Members::getFlexyOptions();
+ $tEngine = new HTML_Template_Flexy($tplOpts);
+
+ switch ($_GET['tab']) {
+ case 6 :
+ $mc =& new Toolkit_Members_EditMemberOnlyContacts(
+ Toolkit_Database::getInstance(),
+ 'edit_contacts',
+ 'post',
+ null,
+ null,
+ null,
+ true
+ );
+ if ($_GET['d'] == 't' && is_numeric($_GET['cid'])) {
+ $mc->removeContact($_GET['cid'], $_GET['id']);
+ }
+ $mc->setConfig($root);
+ $mc->configureForm();
+ $out = $mc->toHtml();
+ break;
+
+ case 5 :
+ $mf =& new Toolkit_Members_EditMemberOnlyFile(
+ Toolkit_Database::getInstance(),
+ 'edit_files'
+ );
+ $mf->setConfig($root);
+ $mf->configureForm();
+ $out = $mf->toHtml();
+ break;
+
+ case 4 :
+ $ma =& new Toolkit_Members_EditMemberOnlyAmenities(
+ Toolkit_Database::getInstance(),
+ 'edit_amenities',
+ 'post',
+ null,
+ null,
+ null,
+ true
+ );
+ $ma->setConfig($root);
+ $ma->configureForm();
+ $out = $ma->toHtml();
+ break;
+
+ case 3 :
+ $mp = new Toolkit_Members_EditPackages(
+ Toolkit_Database::getInstance(),
+ $tEngine
+ );
+ $mp->setupPage();
+ $out = $mp->getPage($nav);
+ break;
+
+ case 2 :
+ // Object to use when rendering the page template
+ $page = new stdClass();
+ // Page navigation
+ $page->nav = $nav->getPageNav();
+
+ // Linked List of member photos
+ $linkedList = new Toolkit_Members_Photos(null, $mid);
+ $linkedList->createMemberList(
+ Toolkit_Database::getInstance(),
+ $root
+ );
+ // Member Object to get calculate attributes about a member
+ $member = new Toolkit_Members_Member(
+ Toolkit_Database::getInstance(),
+ $root
+ );
+ // Server side caching
+ $cache = new Cache_Lite(Toolkit_Members::getCacheOptions());
+ // Image server for processing uploaded images
+ $is = new Toolkit_Image_Server();
+
+ if ($member->canAddPhotos($linkedList, $root)) {
+ $aForm = new Toolkit_Members_AddPhoto(
+ Toolkit_Database::getInstance(),
+ 'new_member_photo',
+ 'post',
+ BASE_URL . "memberdb/index.php?Option=Member&Action=Edit&tab=2",
+ '',
+ null,
+ true
+ );
+ $aForm->configureForm($root);
+ $page->uploadForm = $aForm->toHtml(
+ $tEngine,
+ $cache,
+ $root,
+ $is,
+ $linkedList
+ );
+ }
+
+ if ($member->hasUploadedPhotos($linkedList)) {
+ $editForms = array();
+ $linkedList->rewind();
+
+ foreach ($linkedList as $i) {
+ $id = $i->getId();
+ $eForm = new Toolkit_Members_EditPhoto(
+ Toolkit_Database::getInstance(),
+ $linkedList,
+ "edit_member_photo_$id",
+ 'post',
+ BASE_URL . "memberdb/index.php?Option=Member&Action=Edit&tab=2",
+ '',
+ array('id' => $id),
+ true
+ );
+ $eForm->configureForm($root);
+ $page->editForms[$id] = $eForm->toHtml(
+ $tEngine,
+ $cache,
+ $is,
+ $root
+ );
+ }
+ }
+
+ // get reference to [photos] section of config file
+ $config =& $root->getItem('section', 'photos');
+ $template =& $config->getItem('directive', 'editGalleryTemplate');
+
+ $tEngine->compile($template->getContent());
+ $out = $tEngine->bufferedOutputObject($page);
+ break;
+
+ case 1 :
+ default :
+ $mr =& new Toolkit_Members_EditMemberOnlyInfo(
+ Toolkit_Database::getInstance(),
+ 'edit_member',
+ 'post',
+ null,
+ null,
+ null,
+ true
+ );
+ $mr->setStates(
+ Toolkit_Common::getStates(
+ Toolkit_Database::getInstance()
+ )
+ );
+ $mr->setConfig($root);
+ $mr->configureForm();
+ $out = $mr->toHtml();
+ break;
+ }
+
+ return $out;
+ }
+
+ // }}}
+
+ // {{{ show()
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @return void
+ * @access public
+ */
+ public function show()
+ {
+ echo $this->toHtml();
+ }
+
+ // }}}
+
+ // {{{ updateNotificationEmail()
+
+ /**
+ * Emails the owner and anyone else who wants to be advised of updates
+ *
+ * A false value in the MEMBER_RECORD_UPDATES_ADVISOR will cause no email
+ * to be sent. all secondary advisees listed in the constructor are carbon
+ * copied in the email.
+ *
+ * Emails are sent out in both HTML and TXT forms.
+ *
+ * @param Config_Container $c Configuration object
+ * @param HTML_Template_Flexy $tEngine Flexy Templating Engine
+ * @param Mail $mail Mail object
+ *
+ * @return boolean result of mailing
+ * @access protected
+ * @since Method available since Release 1.5
+ */
+ static public function updateNotificationEmail(
+ Config_Container $c,
+ HTML_Template_Flexy $tEngine,
+ Mail $mail
+ ) {
+ if (MEMBER_RECORD_UPDATES_ADVISOR === false) {
+ return;
+ } else {
+ try {
+ $sql = "
+ SELECT member_name
+ FROM member
+ WHERE member_id = :member_id";
+ $dbh = Toolkit_Database::getInstance();
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(':member_id', $_GET['id'], PDO::PARAM_INT);
+ $stmt->execute();
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+ $memberName = $row['member_name'];
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ $page = new StdClass;
+
+ $page->member = $memberName;
+ $page->url = ($_SERVER['HTTPS'] == 'on') ? BASE_SECURE_URL : BASE_URL;
+ $page->email = OWNER_EMAIL;
+ $page->siteName = SITENAME;
+ $page->link = 'link';
+
+ $tEngine->compile('emailOwner.tpl');
+ // Merge the compiled template with the $page object.
+ $htmlMsg = $tEngine->bufferedOutputObject($page);
+
+ $msg = "
+
$memberName
+
+ Has updated thier business record and is now in a pending
+ state. To approve / reject thier changes you can either log
+ into your {$page->siteName} admin area or follow this
+ {$page->link}
+
';
+ }
+
+ // }}}
+ // {{{ createNav()
+
+ /**
+ * Creates the subnav structure used for the multipage forms
+ *
+ * @author Jamie Kahgee
+ *
+ * @return string UL list of navigation
+ *
+ * @access protected
+ * @since Method available since Release 1.0.0
+ */
+ protected function createNav()
+ {
+ if (array_walk($this->navConfig, array($this, 'makeLiLinks'))) {
+ return '
'.$this->nav.'
';
+ }
+ }
+
+ // }}}
+ // {{{ setupRenderers()
+
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ $renderer =& new HTML_QuickForm_Renderer_Object(true);
+
+ $this->accept($renderer);
+
+ $this->template =& new HTML_Template_Flexy($this->options);
+
+ // Make the view a copy of the $this object
+ // That way we have access to call functions in
+ // this class from within the template.
+ $this->view = $this;
+ $this->view->form = $renderer->toObject();
+ $this->template->compile($this->formTemplate);
+ }
+
+ // }}}
+ // {{{ toHTML()
+
+ /**
+ * Renders the form
+ *
+ * sets the page the form should be redirected to instead of coming back
+ * around to itself.
+ *
+ * @author Jamie Kahgee
+ * @return string The rendered form
+ * @access public
+ * @since Method available since Release 1.0.0
+ */
+ public function toHTML()
+ {
+ // We need to validate (and freeze if needed)
+ // before we render the form. That way the
+ // template knows about any errors on the form.
+ $this->validated = $this->validate();
+
+ if ($this->validated) {
+ $processed = $this->process(array(&$this, 'processData'), $this->mergeFiles);
+ }
+
+ // ProcessData handles settingup the lat/lon coordinates if they were not entered
+ // into the form. these values ar calculated and then inserted into the forms
+ // element values. So we need to process the data first and then render the form.
+ $this->setupRenderers();
+
+ return $this->template->bufferedOutputObject($this->view);
+ }
+
+ // }}}
+ // {{{ show()
+
+ /**
+ * Determine which form to show to the user
+ *
+ * @author Jamie Kahgee
+ * @return void
+ * @access public
+ */
+ public function show()
+ {
+ switch ($_GET['a']) {
+ case 'add' :
+ $addPostCard =& new Toolkit_Postcards_addcard('edit_postcard',
+ 'post', null, null, null, true);
+ $addPostCard->show();
+ break;
+
+ case 'list' :
+ default :
+ break;
+ }
+ }
+
+ // }}}
+}
+?>
diff --git a/Toolkit/Postcards/AddCard.php b/Toolkit/Postcards/AddCard.php
new file mode 100755
index 0000000..16f9f12
--- /dev/null
+++ b/Toolkit/Postcards/AddCard.php
@@ -0,0 +1,41 @@
+
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: AddCard.php,v 1.1.1.1 2009/09/17 20:08:57 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ * @see References to other sections (if any)...
+ */
+
+/**
+ * Short description for class
+ *
+ * Long description (if any) ...
+ *
+ * @category Postcards
+ * @package Toolkit_Postcards
+ * @author Jamie Kahgee
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version Release: @package_version@
+ * @link http://demo.gaslightmedia.com
+ * @see References to other sections (if any)...
+ */
+class Toolkit_Postcards_AddCard
+ extends Toolkit_FormBuilder implements Toolkit_Form
+{
+}
+?>
diff --git a/Toolkit/Postcards/templates/subnav.tpl b/Toolkit/Postcards/templates/subnav.tpl
new file mode 100755
index 0000000..23ece43
--- /dev/null
+++ b/Toolkit/Postcards/templates/subnav.tpl
@@ -0,0 +1,2 @@
+
+
{createSubNav():h}
diff --git a/Toolkit/Press/Newsletter.php b/Toolkit/Press/Newsletter.php
new file mode 100755
index 0000000..9f19852
--- /dev/null
+++ b/Toolkit/Press/Newsletter.php
@@ -0,0 +1,356 @@
+
+ * @copyright 2008 Gaslight Media
+ * @license Gaslight Media
+ * @version CVS: $Id: Newsletter.php,v 1.3 2009/12/15 20:18:16 jamie Exp $
+ * @link <>
+ */
+
+/**
+ * Description for require_once
+ */
+require_once BASE.'classes/class_db.inc';
+
+/**
+ * Description for require_once
+ */
+require_once BASE.'classes/class_template.inc';
+
+/**
+ * Toolkit_PressNewsletter
+ *
+ * Updated version of Press News display
+ *
+ * @category Toolkit
+ * @package Toolkit_Press
+ * @author Steve Sutton
+ * @copyright 2008 Gaslight Media
+ * @license Gaslight Media
+ * @version Release: @package_version@
+ * @link <>
+ */
+class Toolkit_Press_Newsletter
+{
+ // {{{ Properties
+
+
+ /**
+ * newscatid for news item
+ * @var string
+ * @access private
+ */
+ private $_newscatid;
+
+ /**
+ * toolbox catid
+ * @var unknown
+ * @access private
+ */
+ private $_toolboxid;
+
+ /**
+ * database omject
+ * @var object
+ * @access protected
+ */
+ protected $DB;
+
+ /**
+ * Flexy Template Options
+ * @var array
+ * @access protected
+ */
+ protected $flexyOptions;
+
+ /**
+ * form elements to be merged with template
+ * @var unknown
+ * @access public
+ */
+ public $elements;
+
+ /**
+ * Flexy template object
+ * @var object
+ * @access public
+ */
+ public $template;
+
+ /**
+ * Page object to be merged in with flexy template
+ * @var object
+ * @access public
+ */
+ public $page;
+ // }}}
+ // {{{ __construct
+
+
+ /**
+ * __construct
+ *
+ * @param object $toolbox GLM_TEMPLATE
+ * @param unknown $catid news catid
+ *
+ * @return void
+ * @access public
+ */
+ function __construct($toolbox, $catid)
+ {
+ $this->page = new glmPage();
+ $this->flexyOptions = array(
+ 'templateDir' => BASE.'Toolkit/Press/templates',
+ 'compileDir' => BASE.'Toolkit/Press/templates/compile',
+ 'forceCompile' => true,
+ 'flexyIgnore' => false,
+ 'allowPHP' => true,
+ 'privates' => true,
+ 'globals' => true,
+ 'globalfunctions' => true,
+ 'textdomain' => BASE_URL,
+ 'debug' => false
+ );
+ $this->toolbox = $toolbox;
+ $this->DB = $toolbox->DB;
+ $this->dbh = Toolkit_Database::getInstance();
+ $this->template = new HTML_Template_Flexy($this->flexyOptions);
+ $this->page->base_url = BASE_URL;
+ $this->page->RESIZED = RESIZED;
+ $this->page->MIDSIZED = MIDSIZED;
+ $this->page->THUMB = THUMB;
+ $this->page->UP_BASE_URL = BASE_URL.'uploads/';
+ $this->setNewscatid($catid);
+ $this->setToolboxid();
+ if ($_REQUEST['newsid']) {
+ $this->getNews($_REQUEST['newsid']);
+ } else {
+ $this->getNewsPage($catid);
+ }
+ $this->getNewsSummary();
+ $this->template->compile('news.html');
+ if (isset($this->elements)) {
+ $this->template->outputObject($this->page, $this->elements);
+ } else {
+ $this->template->outputObject($this->page);
+ }
+ }
+
+
+ // }}}
+ // {{{ getNews
+
+
+ /**
+ * getNews
+ *
+ * Grab the news
+ *
+ * @param unknown $id id for table news
+ *
+ * @return void
+ * @access public
+ */
+ function getNews($id)
+ {
+ $query = "
+ SET datestyle TO 'sql,us';
+ SELECT *
+ FROM news
+ WHERE id = $id";
+ $news_data = $this->DB->db_auto_get_data($query);
+ if (is_array($news_data)) {
+ $this->page->pr_date = $news_data[0]["pr_date"];
+ $this->page->title = $news_data[0]["title"];
+ $this->page->header = $news_data[0]["header"];
+ if ($news_data[0]['image']) {
+ $this->page->image = $news_data[0]['image'];
+ $this->page->imgclass = "imageleft";
+ if ($news_data[0]['imagename']) {
+ $this->page->imagename = $news_data[0]['imagename'];
+ }
+ }
+ $this->page->description = $this->toolbox->keyword_replace($news_data[0]["description"]);
+ if ($news_data[0]['file'] != '') {
+ $this->page->file = $news_data[0]['file'];
+ if ($news_data[0]['filename']) {
+ $this->page->filename = $news_data[0]['filename'];
+ }
+ }
+ $query = "
+ SELECT *
+ FROM news_block
+ WHERE news_id = {$news_data[0]['id']}
+ ORDER BY pos";
+ $news_block_data = $this->DB->db_auto_get_data($query);
+ if (is_array($news_block_data)) {
+ for ($i = 0; $i < count($news_block_data); ++$i) {
+ $val = $news_block_data[$i];
+ $this->page->section[$i]['align'] = ($i%2==0) ? "right": "left";
+ $this->page->section[$i]['imgclass'] = ($i%2==0) ? "imageright": "imageleft";
+ $this->page->section[$i]['header'] = $val["header"];
+ if ($val['image']) {
+ $this->page->section[$i]['image'] = $val["image"];
+ }
+ $this->page->section[$i]['description'] = $this->toolbox->keyword_replace($val["description"]);
+ if ($val['file'] != '') {
+ $this->page->section[$i]['file'] = $val["file"];
+ if ($val['file']['filename']) {
+ $this->page->section[$i]['filename'] = $val["filename"];
+ }
+ }
+ }
+ }
+ }
+ $this->template->compile('news.html');
+ }
+
+
+ // }}}
+ // {{{ getNewsPage
+
+
+ /**
+ * getNewsPage
+ *
+ * get the current press newsletter
+ *
+ * @param unknown $id category id
+ *
+ * @return void
+ * @access public
+ */
+ function getNewsPage($id = null)
+ {
+ // get news with catid = $newscatid
+ $query = "
+ SELECT id,catid,title,status
+ FROM news
+ WHERE catid = {$id}
+ AND status = 'current'";
+ $data = $this->DB->db_auto_get_data($query);
+ if (is_array($data)) {
+ $catid = $data[0]['id'];
+ $id = $data[0]['id'];
+ $this->getNews($id);
+ }
+ }
+
+
+ // }}}
+ // {{{ getNewsSummary
+
+
+ /**
+ * getNewsSummary
+ *
+ * get summary of the archives + current new srelease
+ *
+ * @return void
+ * @access public
+ */
+ function getNewsSummary()
+ {
+ $query = "SET datestyle TO 'SQL,US';
+ SELECT id,pr_date,title
+ FROM news
+ WHERE catid = ".$this->_newscatid."
+ AND status != 'queued'
+ ORDER BY status desc,pr_date desc";
+ $data2 = $this->DB->db_auto_get_data($query);
+ if (is_array($data2)) {
+ foreach ($data2 as $key => $val) {
+ $this->page->news_summary[$val['id']]['pr_date'] = $val['pr_date'];
+ $this->page->news_summary[$val['id']]['news_page'] = BASE_URL.'index.php?catid='.$_REQUEST['catid'].'&newsid='.$val["id"];
+ $this->page->news_summary[$val['id']]['title'] = $val['title'];
+ }
+ }
+ }
+
+
+ // }}}
+ // {{{ getRSSFeed
+
+
+ /**
+ * Create RSS Feed for the newsletter/press
+ * This gives client ability to send a rss to their users so
+ * they are up to date on all newsletter post.
+ * Pulls all non archived news
+ *
+ * @access public
+ * @return string
+ */
+ function getRSSFeed()
+ {
+ $options = array(
+ "indent" => " ",
+ "linebreak" => "\n",
+ "typehints" => false,
+ "addDec1" => true,
+ "encoding" => "UTF-8",
+ "rootName" => "rdf:RDF",
+ "defaultTagName" => "item",
+ );
+ $sql = "
+ SELECT *
+ FROM news
+ WHERE status != 'archived'
+ ORDER BY status desc,pr_date desc";
+ try {
+ $data = $this->dbh->query($sql)->fetchAll();
+ echo '