From: Steve Sutton Date: Fri, 5 Feb 2010 19:29:28 +0000 (+0000) Subject: new revamp for troutcreek X-Git-Tag: v1.0.0~130 X-Git-Url: http://cvs2.gaslightmedia.com/gitweb/?a=commitdiff_plain;h=96501ec179da6c13e740207b9886ee2d26bdb6b3;p=web%2FTroutCreek.git new revamp for troutcreek --- 96501ec179da6c13e740207b9886ee2d26bdb6b3 diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..b5b8cd6 --- /dev/null +++ b/.htaccess @@ -0,0 +1,31 @@ + +Order allow,deny +Deny from all + + +Order allow,deny +Deny from all + +#ErrorDocument 404 /404.html +RewriteEngine On +AddDefaultCharset utf-8 +RewriteBase /www.troutcreek.com/ +#RewriteCond %{HTTP_HOST} !^(.*)\.troutcreek\.com$ [NC] +#RewriteRule ^(.*)$ http://www.troutcreek.com/$1 [R=301,L] +RewriteRule ^VisitorGuide/(.*)/$ pdf-download.php?uidpdf=$1&pdf_file=VisitorGuide [L] +RewriteRule ^.*-([0-9]*)/([0-9]*)/$ index.php?catid=$1&photo_catid=$2 [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 + +# short urls +RewriteCond %{REQUEST_URI} !(^.*-([0-9]*)/$) +RewriteRule ^([A-Za-z0-9_-]*)/$ index.php?glmPage=$1 [L] + +############### +## Templates ## +############### +# View flexy templates as php files +AddType application/x-httpd-php .tpl 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/CKImages/Connector.php b/Toolkit/CKImages/Connector.php new file mode 100644 index 0000000..9f288b2 --- /dev/null +++ b/Toolkit/CKImages/Connector.php @@ -0,0 +1,360 @@ + + * @copyright 2009 Jamie Kahgee + * @license http://www.gaslightmedia.com Gaslightmedia + * @version CVS: $Id: Connector.php,v 1.8 2009/11/15 19:12:23 jamie Exp $ + * @link http://demo.gaslightmedia.com + */ + + +/** + * Connects the CKImage browser to the server for image manipulation + * + * @category CKImages + * @package Toolkit_CKImages + * @author Jamie Kahgee + * @copyright 2009 Jamie Kahgee + * @license http://www.gaslightmedia.com Gaslightmedia + * @version Release: @package_version@ + * @link http://demo.gaslightmedia.com + */ +class Toolkit_CKImages_Connector +{ + // {{{ setDbh() + + + /** + * Sets the database handler for the object to use + * + * @param PDO $pdo PHP Data Object + * + * @return void + * @access public + */ + public function setDbh(PDO $pdo) + { + $this->dbh = $pdo; + } + + // }}} + + // {{{ createFolder() + + + /** + * Creates a new folder + * + * @return void + * @access public + */ + public function createFolder() + { + // get the folder id + $folder = $_GET['name']; + $parent = ctype_digit((string) $_GET['folder']) ? $_GET['folder'] : 1; + + if (ctype_digit((string) $_GET['parentFolder'])) { + $parent = $_GET['parentFolder']; + } + // unset unneeded param values + unset($_GET['command'], $_GET['name'], $_GET['parentFolder']); + + try { + $sql = " + INSERT INTO ckeditor_folders(name, parent) + VALUES (:name, :parent)"; + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(':name', $folder, PDO::PARAM_INT); + $stmt->bindParam(':parent', $parent, PDO::PARAM_INT); + $stmt->execute(); + header('Location:' . BASE_URL . 'Toolkit/CKImages/browser.php?' . http_build_query($_GET)); + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + + // {{{ deleteFile() + + + /** + * Deletes a file from the image server for client + * + * @param Toolkit_Image_Server $is Image Server Object + * + * @return void + * @access public + */ + public function deleteFile(Toolkit_Image_Server $is) + { + // Get offset where target img starts at + $start = strrpos($_GET['img'], '/') + 1; + // get the image name + $img = substr($_GET['img'], $start); + // unset unneeded param values + unset($_GET['command'], $_GET['img']); + + $is->imageDelete($img); + + try { + $sql = " + DELETE FROM ckeditor_images + WHERE name_on_disk = :nod"; + + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(':nod', $img, PDO::PARAM_STR); + $stmt->execute(); + header('Location:' . BASE_URL . 'Toolkit/CKImages/browser.php?' . http_build_query($_GET)); + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + // {{{ deleteFolder() + + + /** + * Deletes a folder and any sub folders + * + * Moves all containing images to home folder so they are not + * inadvertently deleted + * + * @param Toolkit_Image_Server $is Image Server used to delete photo + * + * @return void + * @access public + */ + public function deleteFolder(Toolkit_Image_Server $is) + { + // get the folder id + $folder = $_GET['folder']; + if ($folder == 1) { + return false; + } + // unset unneeded param values + unset($_GET['command'], $_GET['tgt']); + $_GET['folder'] = 1; + + try { + $tree = Toolkit_Common::getHierarchicalTreeStructure( + $this->dbh, + 'ckeditor_folders', + 'id', + 'parent', + 'id', + $folder, + 0, + false + ); + + $sql = " + UPDATE ckeditor_images + SET folder = 1 + WHERE folder = :folder"; + + $imgStmt = $this->dbh->prepare($sql); + + $sql = " + DELETE FROM ckeditor_folders + WHERE id = :folder"; + $fldrStmt = $this->dbh->prepare($sql); + while (list($tgt) = each($tree)) { + $imgStmt->bindParam(':folder', $tgt, PDO::PARAM_INT); + $imgStmt->execute(); + + $fldrStmt->bindParam(':folder', $tgt, PDO::PARAM_INT); + $fldrStmt->execute(); + } + // These cookies are defined in the libjs/image_selector.js file + // when the tree is created. + unset($_COOKIE['glm_image_browser_open'], $_COOKIE['glm_image_browser_selected']); + header('Location:' . BASE_URL . 'Toolkit/CKImages/browser.php?' . http_build_query($_GET)); + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + + // {{{ browseImages() + + + /** + * Creates the browser window + * + * @param HTML_Template_Flexy $tEngine Flexy Rendering Engine Object + * @param Toolkit_Image_Server $is Image Server + * + * @return string HTML page to browse images + * @access public + */ + public function browseImages( + HTMl_Template_Flexy $tEngine, + Toolkit_Image_Server $is + ) { + $page = new stdClass(); + $page->originalPath = ORIGINAL; + $page->imageManager = IMAGE_MANAGER; + + $folder = ctype_digit((string) $_GET['folder']) + ? "&folder={$_GET['folder']}" : ''; + $form = new HTML_QuickForm( + 'quick_upload', + 'post', + BASE_URL . "Toolkit/CKImages/connector.php?CKEditor={$_GET['CKEditor']}&CKEditorFuncNum={$_GET['CKEditorFuncNum']}&langCode={$_GET['langCode']}&command=UploadFile$folder" + ); + $form->addElement('file', 'upload'); + $page->quickUploadForm = $form->toHtml(); + + $folders = new Toolkit_CKImages_Folders($this->dbh); + $page->folders = $folders->getFolders(0); + + try { + $folder = ctype_digit((string) $_GET['folder']) + ? $_GET['folder'] : 1; + $sql = " + SELECT * + FROM ckeditor_images + WHERE folder = :folder + ORDER BY id ASC"; + + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(':folder', $folder, PDO::PARAM_INT); + $stmt->execute(); + + $images = $stmt->fetchAll(PDO::FETCH_ASSOC); + + foreach ($images as &$i) { + $dimensions = $is->getImageSize($page->originalPath . $i['name_on_disk']); + list($i['width'], $i['height'],) = $dimensions; + } + + $page->images = $images; + + $tEngine->compile('thumbnails.html'); + $tEngine->outputObject($page); + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + + // {{{ handleUpload() + + + /** + * Handles inserting the upload into the database + * + * @param string $imageName image to insert + * @param array $dimensions dimensions of the image + * + * @return object Return description (if any) ... + * @access protected + */ + protected function handleUpload($imageName, array $dimensions) + { + try { + $folder = ctype_digit((string) $_GET['folder']) + ? $_GET['folder'] : 1; + $sql = " + INSERT INTO ckeditor_images (file_name, name_on_disk, folder, + original_width, original_height) + VALUES (:fname, :nod, :folder, :width, :height)"; + + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam( + ':fname', + $_FILES['upload']['name'], + PDO::PARAM_STR + ); + $stmt->bindParam(':nod', $imageName, PDO::PARAM_STR); + $stmt->bindValue(':folder', $folder, PDO::PARAM_INT); + $stmt->bindValue(':width', $dimensions['oWidth'], PDO::PARAM_INT); + $stmt->bindValue(':height', $dimensions['oHeight'], PDO::PARAM_INT); + + + return $stmt->execute(); + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + + // {{{ quickUpload() + + + /** + * send uploaded image to image server + * + * @param Toolkit_Image_Server $is Image Server + * + * @return void + * @access public + */ + public function quickUpload(Toolkit_Image_Server $is) + { + ob_start(); + $imageName = $is->imageUpload('upload'); + ob_end_clean(); + if ($imageName) { + $dimensions = $is->getImageSize(ORIGINAL . $imageName); + list($i['oWidth'], $i['oHeight'],) = $dimensions; + $this->handleUpload($imageName, $i); + } + + unset($_GET['command']); + header('Location:' . BASE_URL . 'Toolkit/CKImages/browser.php?' . http_build_query($_GET)); + } + + // }}} + + // {{{ uploadFile() + + + /** + * send uploaded image to image server and select that file to be used + * + * @param Toolkit_Image_Server $is Image server object + * + * @return void + * @access public + */ + public function uploadFile(Toolkit_Image_Server $is) + { + ob_start(); + $imageName = $is->imageUpload('upload'); + ob_end_clean(); + $funcNum = ctype_digit((string) $_GET['CKEditorFuncNum']) + ? $_GET['CKEditorFuncNum'] : 1; + + echo ''; + } + + // }}} +} +?> diff --git a/Toolkit/CKImages/Factory.php b/Toolkit/CKImages/Factory.php new file mode 100644 index 0000000..a693896 --- /dev/null +++ b/Toolkit/CKImages/Factory.php @@ -0,0 +1,83 @@ + + * @copyright 2009 Jamie Kahgee + * @license http://www.gaslightmedia.com Gaslightmedia + * @version CVS: $Id: Factory.php,v 1.1 2009/09/24 14:43:02 jamie Exp $ + * @link http://demo.gaslightmedia.com + * @see References to other sections (if any)... + */ + + +/** + * CKImage Factory + * + * @category CKImages + * @package Toolkit_CKImages + * @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_CKImages_Factory +{ + // {{{ properties + + /** + * array of instances + * @var array + * @access public + * @static + */ + public static $instances = array(); + + // }}} + // {{{ init() + + /** + * initialize the factory + * + * @return void + * @access public + * @static + */ + public static function init() + { + } + + // }}} + // {{{ &instance() + + /** + * Get a single instance of an object + * + * @param string $class Class name to create + * + * @return mixed instantiated object + * @access public + * @static + */ + public static function &instance($class) + { + $class = "Toolkit_CKImages_$class"; + + if (empty(Toolkit_CKImages_Factory::$instances)) { + Toolkit_CKImages_Factory::$instances[$class] = new $class; + } + + return Toolkit_CKImages_Factory::$instances[$class]; + } + + // }}} +} +?> diff --git a/Toolkit/CKImages/Folders.php b/Toolkit/CKImages/Folders.php new file mode 100644 index 0000000..2858948 --- /dev/null +++ b/Toolkit/CKImages/Folders.php @@ -0,0 +1,243 @@ + + * @copyright 2009 Jamie Kahgee + * @license http://www.gaslightmedia.com Gaslightmedia + * @version CVS: $Id: Folders.php,v 1.6 2009/10/27 14:39:27 jamie Exp $ + * @link http://demo.gaslightmedia.com + * @see References to other sections (if any)... + */ + +/** + * Handles create a UL list to simulate a folder hierarchy + * + * @category CKImages + * @package Toolkit_CKImages + * @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_CKImages_Folders +{ + // {{{ properties + + + /** + * Levels deep we are into the hierarchy + * @var integer + * @access private + */ + private $_lvlsOpen = 0; + + /** + * The previous level we were at + * @var integer + * @access private + */ + private $_prevLvl = 0; + + // }}} + + // {{{ __construct() + + /** + * Constructor + * + * @param PDO $pdo PHP Data Object + * + * @return void + * @access public + */ + public function __construct(PDO $pdo) + { + $this->dbh = $pdo; + } + + // }}} + + // {{{ closeFolder() + + + /** + * Closes a folder level + * + * @return string closing ul tag + * @access protected + */ + protected function closeFolder() + { + return "\n"; + } + + // }}} + // {{{ closeNode() + + + /** + * Closes a node + * + * @return string closing li tag + * @access protected + */ + protected function closeNode() + { + return "\n\t"; + } + + // }}} + // {{{ createFolder() + + + /** + * Creates a folder level + * + * @return string opening ul tag + * @access protected + */ + protected function createFolder() + { + return "\n
    "; + } + + // }}} + // {{{ createLink() + + + /** + * Creates a folder link so we can browse to each folder + * + * @param array $row Folder information + * + * @return string anchor link for folder + * @access protected + */ + protected function createLink(array $row) + { + $format = '%s'; + + $link = sprintf( + $format, + ($_GET['folder'] == $row['id']) ? 'clicked' : null, + $_GET['CKEditor'], + $_GET['CKEditorFuncNum'], + $_GET['langCode'], + $row['id'], + $row['name'] + ); + + return $link; + } + + // }}} + + // {{{ fetchFoldersArray() + + + /** + * Fetches a tree hierarchy of the folder structure into a linear array + * + * @param integer $start node to start at + * + * @return array folder structure with levels + * @access protected + */ + protected function fetchFoldersArray($start) + { + return Toolkit_Common::getHierarchicalTreeStructure( + $this->dbh, + 'ckeditor_folders', + 'id', + 'parent', + 'id', + $start + ); + } + + // }}} + + // {{{ getFolders() + + + /** + * Gets the folders ul list + * + * @param integer $parent start at a certain level + * + * @return string list of folders + * @access public + */ + public function getFolders($parent = 0) + { + $folders = $this->fetchFoldersArray($parent); + try { + $sql = " + SELECT * + FROM ckeditor_folders + WHERE id = :id"; + + $stmt = $this->dbh->prepare($sql); + foreach ($folders as $i => $j) { + $stmt->bindParam(':id', $i, PDO::PARAM_INT); + $stmt->execute(); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + + if ($j == $this->_prevLvl) { + $tree .= $this->openNode($row); + $tree .= $this->createLink($row); + $this->_prevLvl = $j; + } elseif ($j > $this->_prevLvl) { + ++$this->_lvlsOpen; + $tree .= $this->createFolder(); + $tree .= $this->openNode($row); + $tree .= $this->createLink($row); + $this->_prevLvl = $j; + } elseif ($j < $this->_prevLvl) { + do { + $tree .= $this->closeNode(); + $tree .= $this->closeFolder(); + } while (--$this->_lvlsOpen > $j); + $tree .= $this->closeNode(); + $tree .= $this->openNode($row); + $tree .= $this->createLink($row); + $this->_prevLvl = $this->_lvlsOpen; + } + } + $tree .= $this->closeFolder(); + return $tree; + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + + // {{{ openNode() + + + /** + * Opens a branch or leaf node + * + * @param array $row Folder information + * + * @return string opening li tag + * @access protected + */ + protected function openNode(array $row) + { + return "\n\t
  • "; + } + + // }}} +} +?> diff --git a/Toolkit/CKImages/assets/.keepme b/Toolkit/CKImages/assets/.keepme new file mode 100644 index 0000000..e69de29 diff --git a/Toolkit/CKImages/browser.php b/Toolkit/CKImages/browser.php new file mode 100644 index 0000000..5a30721 --- /dev/null +++ b/Toolkit/CKImages/browser.php @@ -0,0 +1,35 @@ + + * @copyright 2009 Jamie Kahgee + * @license http://www.gaslightmedia.com/ Gaslightmedia + * @version CVS: $Id: browser.php,v 1.3 2009/11/15 19:12:23 jamie Exp $ + * @link <> + * @see References to other sections (if any)... + */ + +/** + * bootstrap + */ +require_once '../../setup.phtml'; + +Toolkit_CKImages_Factory::init(); +$connector = Toolkit_CKImages_Factory::instance('Connector'); +$connector->setDbh(Toolkit_Database::getInstance()); +$flexyOpts = $GLOBALS['flexyOptions']; +$flexyOpts['templateDir'] = BASE . 'Toolkit/CKImages/templates/'; +$flexyOpts['compileDir'] = BASE . 'Toolkit/CKImages/templates/compiled/'; +$tEngine = new HTML_Template_Flexy($flexyOpts); +$is = new Toolkit_Image_Server; + +$connector->browseImages($tEngine, $is); +?> diff --git a/Toolkit/CKImages/connector.php b/Toolkit/CKImages/connector.php new file mode 100644 index 0000000..fa87860 --- /dev/null +++ b/Toolkit/CKImages/connector.php @@ -0,0 +1,53 @@ + + * @copyright 2009 Jamie Kahgee + * @license http://www.gaslightmedia.com/ Gaslightmedia + * @version CVS: $Id: connector.php,v 1.3 2009/11/15 19:12:23 jamie Exp $ + * @link <> + * @see References to other sections (if any)... + */ + +/** + * bootstrap + */ +require_once '../../setup.phtml'; + +Toolkit_CKImages_Factory::init(); +$connector = Toolkit_CKImages_Factory::instance('Connector'); +$connector->setDbh(Toolkit_Database::getInstance()); + +switch ($_GET['command']) { +case 'CreateFolder' : + $connector->createFolder(); + break; + +case 'DeleteFile' : + $connector->deleteFile(new Toolkit_Image_Server); + break; + +case 'DeleteFolder' : + $connector->deleteFolder(new Toolkit_Image_Server); + break; + +case 'Upload' : + $connector->uploadFile(new Toolkit_Image_Server); + break; + +case 'UploadFile' : + $connector->quickUpload(new Toolkit_Image_Server); + break; + +default : + die('not yet implemented'); + $connector->throwError(); + break; +} +?> diff --git a/Toolkit/CKImages/database/ckeditorImages.sql b/Toolkit/CKImages/database/ckeditorImages.sql new file mode 100644 index 0000000..1f0ae0d --- /dev/null +++ b/Toolkit/CKImages/database/ckeditorImages.sql @@ -0,0 +1,27 @@ +drop table ckeditor_folders; + +create table ckeditor_folders( +id serial primary key, +name text not null, +parent integer default 1 not null +); + +grant all on ckeditor_folders_id_seq to nobody; +grant all on ckeditor_folders to nobody; + +insert into ckeditor_folders(id, name, parent) values(1, 'root', 0); + +drop table ckeditor_images; + +create table ckeditor_images( +id serial primary key, +create_date date default current_date, +file_name text not null, +name_on_disk text not null, +original_width text not null, +original_height text not null, +folder integer default 1 references ckeditor_folders (id) on delete set default +); + +grant all on ckeditor_images_id_seq to nobody; +grant all on ckeditor_images to nobody; \ No newline at end of file diff --git a/Toolkit/CKImages/libjs/image_selector.js b/Toolkit/CKImages/libjs/image_selector.js new file mode 100644 index 0000000..c6becfb --- /dev/null +++ b/Toolkit/CKImages/libjs/image_selector.js @@ -0,0 +1,123 @@ +var IMAGE_SELECTOR = +{ + parentFolder: null, + + init: function() + { + tree1 = new tree_component(); + tree1.init($("#folders"), { + cookies : { + prefix : "glm_image_browser", + opts : { path : '/' } + }, + ui : { + animation : 500 + } + }); + + // Make the tree default to all opened + $('#folders li.closed') + .toggleClass('open') + .toggleClass('closed'); + + $('#folders a').click(IMAGE_SELECTOR.viewFolder); + + // Stop clicks on the LI elements, so the folders branches + // will not close. + $('#folders li').click(function(event) { + event.stopImmediatePropagation(); + }); + + $('div.thumb a.CKImageUse').click(function() { + var img = $(this).siblings('img'); + window.opener.CKEDITOR.tools.callFunction(1, img.attr('title')); + window.close(); + }); + + $('div.thumb a.CKImageDelete').click(function(event) { + event.preventDefault(); + if (confirm('Are you sure you want to delete this image?')) { + var img = $(this).siblings('img').attr('title'); + var href = window.location.href.replace(/(.*)browser.php(.*)/, '$1connector.php$2&command=DeleteFile&img=' + img); + + window.location.href = href; + } + }); + + $('#imageDialog').dialog({ + bgiframe : true, + autoOpen : false, + resizable: false, + modal : true, + buttons : { + Cancel : function() { + $(this).dialog('close'); + }, + 'Upload Selected File' : function() { + if ($('#imageDialog form input[type=file]').val()) { + $('.ui-dialog-buttonpane button').attr('disabled', true); + $('#imageDialog form').trigger('submit'); + } else { + alert('You need to select a file first'); + } + } + } + }); + + $('#upload').click(function() { + $('#imageDialog').dialog('open'); + }); + + $('#newFolder').submit(IMAGE_SELECTOR.createFolder); + $('#folderDialog').dialog({ + bgiframe : true, + autoOpen : false, + resizable: false, + modal : true, + buttons: { + Cancel : function() { + $('#folderName').removeClass('ui-state-error'); + $(this).dialog('close'); + }, + 'Create' : IMAGE_SELECTOR.createFolder + } + }); + $('#folderNew').click(function() { + $('#folderDialog').dialog('open'); + }); + $('#folderDelete').click(function() { + if (confirm('Are you sure you want to delete this folder?')) { + var href = window.location.href.replace(/(.*)browser.php(.*)/, '$1connector.php$2&command=DeleteFolder'); + + window.location.href = href; + } + }); + }, + + createFolder: function(event) + { + event.preventDefault(); + // don't submit empty folder + var folderName = $('#folderName'); + var val = folderName.val(); + if (val == '') { + alert('You need to type a folder name first'); + return false; + } else { + $('.ui-dialog-buttonpane button').attr('disabled', true); + var href = window.location.href.replace(/(.*)browser.php(.*)/, '$1connector.php$2&command=CreateFolder&name=' + $('#folderName').val()); + if (IMAGE_SELECTOR.parentFolder != null) { + href += '&parentFolder=' + IMAGE_SELECTOR.parentFolder; + IMAGE_SELECTOR.parentFolder = null; + } + window.location.href = href; + } + }, + + viewFolder: function(event) + { + location.href = $(this).attr('href'); + } +}; + +$(document).ready(IMAGE_SELECTOR.init); diff --git a/Toolkit/CKImages/styles.css b/Toolkit/CKImages/styles.css new file mode 100755 index 0000000..3787fea --- /dev/null +++ b/Toolkit/CKImages/styles.css @@ -0,0 +1,146 @@ +body { + font-family: arial, sans-serif; + font-size: 11px; + background: #E3E3C7; + margin: 0; + padding: 0; +} +#wrapper { + width: 720px; + height: 1%; + overflow: hidden; + margin: 10px 0px 5px 10px; +} +h1 { + font-size: 24px; + margin: 0 0 10px 0; +} +#toolbar { + background: #F1F1E3; + width: 124px; + border: 1px solid #D5D59D; + float: left; + padding: 8px; + margin-right: 10px; +} +#toolbar > ul { + border-bottom: 1px solid #333; + padding: 0 0 6px 0; + margin: 0 0 6px 0; + } +#toolbar > ul, #toolbar > ul li { + list-style: none; + display: block; +} +#toolbar > ul li { + padding: 2px 2px 2px 26px; + line-height: 18px; + border: 1px solid #F1F1E3; + margin: 0; + background-position: 2px center; + background-repeat: no-repeat; + text-decoration: underline; + cursor: hand; + cursor: pointer; +} +#toolbar > ul li:hover { + border: 1px solid #D5D59D; + text-decoration: none; +} +#toolbar #upload { + background-image: url(http://app.gaslightmedia.com/assets/icons/image_add.png); +} +#toolbar #folderNew { + background-image: url(http://app.gaslightmedia.com/assets/icons/folder_add.png); +} +#toolbar #folderDelete { + background-image: url(http://app.gaslightmedia.com/assets/icons/folder_delete.png); +} +.tree ul { + margin: 0; + padding-top: 1px; +} +.tree li a { + background-image: url(http://app.gaslightmedia.com/assets/icons/folder.png); +} +.tree li.open { + background: none; + } +#pred_1 { + padding-left: 3px; + padding-top: 3px; +} +.tree li li.open { + background: transparent url(http://app.gaslightmedia.com/libjs/jsTree/source/images/li.gif) no-repeat scroll 7px 7px; +} +/* Main Section */ +#photo-gallery { + width: 560px; + height: 1%; + overflow: hidden; +} +.thumb { + width: 120px; + height: 150px; + float: left; + margin-right: 20px; + margin-bottom: 20px; + background: white; + font-size: 10px; +} +.rowTop { + height: 1%; + overflow: hidden; +} +.thumb img { + display: block; + margin: 0px 10px 2px 10px; + border: 1px dotted #ccc; + clear: left; +} +.CKImageUse { + display: block; + background: url(http://app.gaslightmedia.com/assets/icons/accept.png) no-repeat; + padding-left: 20px; + line-height: 16px; + margin: 5px 10px 0px 10px; + border: 1px solid #fff; + text-decoration: underline; +} +.CKImageUse:link {color: black;} +.CKImageUse:visited {color: black;} +.CKImageUse:hover {color: green; text-decoration: none; border: 1px solid white} +.CKImageUse:actove {color: black;} + +.CKImageName { + display: none; +} +.CKImageDelete { + background: url(http://app.gaslightmedia.com/assets/icons/cross.png) no-repeat; + width: 16px; + height: 16px; + display: block; + float: right; + text-indent: -9000px; + margin: 3px 2px; + margin-right: 6px; + } +.CKImageView { + background: url(http://app.gaslightmedia.com/assets/icons/image.png) no-repeat; + width: 16px; + height: 16px; + display: block; + float: left; + text-indent: -9000px; + margin: 3px 10px; +} +.CKImageProperties { + margin: 3px; + float: left; +} +.CKImageDate { + display: none; +} +#menuFolder, #menuImage, #column { + display: none; +} \ No newline at end of file diff --git a/Toolkit/CKImages/templates/compiled/.cvsignore b/Toolkit/CKImages/templates/compiled/.cvsignore new file mode 100644 index 0000000..7f1398d --- /dev/null +++ b/Toolkit/CKImages/templates/compiled/.cvsignore @@ -0,0 +1 @@ +* */* diff --git a/Toolkit/CKImages/templates/compiled/.keepme b/Toolkit/CKImages/templates/compiled/.keepme new file mode 100644 index 0000000..e69de29 diff --git a/Toolkit/CKImages/templates/thumbnails.html b/Toolkit/CKImages/templates/thumbnails.html new file mode 100755 index 0000000..e0e6289 --- /dev/null +++ b/Toolkit/CKImages/templates/thumbnails.html @@ -0,0 +1,63 @@ + + + +Thumbnail Images + + + + + + + + + + + + + +
    +

    GLM Image Browser

    +
    +
    +
      +
    • Upload New Image
    • +
    +
      +
    • Create New Folder
    • +
    • Delete This Folder
    • +
    +
    + Folders + {folders:h} +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    + {quickUploadForm:h} +
    + + diff --git a/Toolkit/Common.php b/Toolkit/Common.php new file mode 100644 index 0000000..7f3eafb --- /dev/null +++ b/Toolkit/Common.php @@ -0,0 +1,1217 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @release CVS: $Id: Common.php,v 1.51 2010/01/28 20:15:40 matrix Exp $ + * @link http://demo.gaslightmedia.com + */ + +/** + * Common collection of functions used throughout the GLM Toolkit + * + * @category Toolkit + * @package Toolkit_Common + * @author Jamie Kahgee + * @copyright 2008 Gaslight Media + * @license http://www.gaslightmedia.com Gaslightmedia + * @link http://demo.gaslightmedia.com + */ +class Toolkit_Common +{ + // {{{ properties + + /** + * Who to send email to when a problem occurs on a live site + * + * This property doesn't matter for the development servers b/c the + * script will display the error encountered and terminate immediately. + * On the live site, a notification will be displayed to the user that + * an unexpected error has occured and will inform them to try again later. + * It will then send an email to the admin alerting them of the email. + * + * @var string + * @access protected + * @see Toolkit_Common::handleError() + */ + protected static $admin = 'jamie@gaslightmedia.com'; + + /** + * Who to set the mail from when emailing errors + * + * @var string + * @access protected + * @see Toolkit_Common::handleError() + */ + protected static $from = 'Gaslight Media Toolkit '; + + // }}} + + // {{{ arrayFlatten() + + /** + * Recursively reduces multi-dimensional arrays to single-dimensional arrays + * + * @param array $array The array to flatten. + * @param int $preserveKeys How to handle array keys + * 0 = Never + * 1 = Strings + * 2 = Always + * @param array &$newArray The new created from the flattening + * + * @return array Single dimensional array. + * @access public + */ + public function arrayFlatten($array, + $preserveKeys = 1, + &$newArray = Array() + ) { + foreach ($array as $key => $child) { + if (is_array($child)) { + $newArray =& Toolkit_Common::arrayFlatten( + $child, + $preserveKeys, + $newArray + ); + } elseif ((int) $preserveKeys + (int) is_string($key) > 1) { + $newArray[$key] = $child; + } else { + $newArray[] = $child; + } + } + return $newArray; + } + + // }}} + + // {{{ cleanArray() + + /** + * removes values from an array where the key ends in '_rmv' + * + * @param array &$values array to clean + * + * @return array array w/ unneeded elements removed + * @access public + * @static + */ + public static function cleanArray(&$values) + { + // 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 $values; + } + + // }}} + // {{{ createEmailBody() + + /** + * Convert the form into an acceptable table to include in email + * + * This function can be called from any form class to generate + * a HTML table that we can use in an email. Elements can be dynamically + * rendered to meet your needs if you wish. + * + * If you wish to have any element(s) rendered differently than what the + * form already rendered them as, you need to define a public method + * named "emailRenderElement" in the calling class that will accept an + * elements name and you can create the rendering template in that class. + * + * Example: + * This example will turn groups like radio buttons or checkboxes + * from lists like: + * [ ] element_one [x] element_two [x] element_three + * ( ) element_one (x) element_two ( ) element_three + * into lists like: + * [ ] element_one ( ) element_one + * [x] element_two (x) element_two + * [x] element_three ( ) element_three + * + * public function &emailRenderElement($e) + * { + * switch ($e) { + * case 'element_one' : + * case 'element_two' : + * case 'element_three' : + * $renderer =& $this->defaultRenderer(); + * $renderer->clearAllTemplates(); + * $renderer->setGroupTemplate('{content}', $e); + * $renderer->setGroupElementTemplate('{element}
    ', $e); + * break; + * + * default : + * $renderer = null; + * break; + * } + * + * return $renderer; + * } + *
    + * + * @param array $newLabels Assoc array of element names and new + * labels to be used in the email form. + * eg [$newLabels['element'] => 'Label'] + * @param array $excludeList Any element that needs to be removed + * from the form when creating the table + * eg [$list = array(e1, e2, e3, etc..)] + * + * @return mixed The table body for the email. + */ + public function createEmailBody( + array $newLabels = array(), + array $excludeList = array() + ) { + $this->freeze(); + // Get the values corresponding to the elements present in the form. + $formData = $this->exportValues(); + // The array keys holds all the names of the elements. + $elements = array_keys($formData); + // Remove any unwanted elements from our elements array. + foreach ($excludeList as $trgt) { + unset($elements[array_search($trgt, $elements)]); + } + + // Which row we are at. + $i = 0; + $table = new HTML_Table(array('class' => 'data')); + // Auto grow the table, since the forms will by dynamic in size. + $table->setAutoGrow(true); + // Get the labels and values of the elements. + foreach ($elements as $name) { + $e =& $this->getElement($name); + // Get the default HTML for each element. + $html = $e->toHtml(); + // If any elements need to have their html + // changed for an email, this function in the + // class should exist and will return a renderer + // object of how the element should be rendered. + if (method_exists($this, 'emailRenderElement')) { + $renderer =& $this->emailRenderElement($name); + // make sure we have an actual rendering object + // if the element doesn't need to be altered it should + // just return null. + if (is_object($renderer)) { + $e->accept(&$renderer); + $html = $renderer->toHtml($name); + // We have to reset the entire forms html + // otherwise we'll just keep adding to it everytime + // we render a new element. + // This is a bit of a hack to make this work (because + // the _html element is supposed to be a private + // property) + $renderer->_html = null; + } + } + // Get the label for the element. + $label = array_key_exists($name, $newLabels) ? + $newLabels[$name] : + $e->getLabel(); + + // Make the row and increment the row counter. + $table->setCellContents($i, 0, $label); + $table->setCellAttributes($i, 0, array('class' => 'label')); + $table->setCellAttributes($i, 1, array('class' => 'field')); + $table->setCellContents($i++, 1, $html); + } + return $table->toHtml();; + } + + // }}} + // {{{ createSQLInsert() + + /** + * Generates a properly formatted sql query to insert data into a table + * + * @param string $table Name of the table to insert into + * @param array $columns Array of column names you want to set in the + * insert statement and bind names + * + * + * Toolkit_Common::createSQLInsert('member', array('name', 'pos')); + * will create the sql statement + * INSERT INTO member (name, pos) VALUES(:name, :pos) + * + * + * @return string Formatted SQL string + * @access public + * @static + */ + public static function createSQLInsert($table, array $columns) + { + $params = implode(', ', $columns); + $bindParams = ':' . implode(', :', $columns); + + return "INSERT INTO $table ($params) VALUES ($bindParams)"; + } + + // }}} + // {{{ createSQLUpdate() + + /** + * Generates a properly formatted sql query to update data in a table + * + * + * Toolkit_Common::createSQLUpdate('member', + * array('name', 'pos'), + * array('id = :id'); + * will create the sql statement + * UPDATE member SET name = :name, pos = :pos WHERE id = :id + * + * + * @param string $table Name of the table to update + * @param array $columns Array of columns names you want to update + * @param array $constraints Constraints to apply to the table to prevent + * running the update on every row in the db + * + * @return string formatted query string + * @access public + * @static + */ + public static function createSQLUpdate( + $table, + array $columns, + array $constraints = null + ) { + $length = count($columns); + for ($i = 0; $i < $length; ++$i) { + $bindParams .= "{$columns[$i]} = :{$columns[$i]}"; + if ($i < ($length - 1)) { + $bindParams .= ', '; + } + } + $sql = "UPDATE $table SET $bindParams"; + + if (!empty($constraints)) { + $sql .= ' WHERE ' . implode(' AND ', $constraints); + } + + return $sql; + } + + // }}} + // {{{ createTables() + + /** + * Read file from parameter and use the PDO parameter to create process file + * + * @param PDO $pdo PHP Data Object to use for DB calls + * @param string $file full path of file to parse + * + * @return void + * @access public + * @static + */ + public static function createTables(PDO $pdo, $file) + { + $sql = file_get_contents($file); + // break multiple queries apart by ';' + $tok = strtok($sql, ';'); + try { + // while we have valid tokens, execute the query + // and grab the next token + while ($tok !== false) { + $pdo->query($tok); + $tok = strtok(';'); + } + } catch (PDOException $e) { + Toolkit_Common::handleError($e); + } + } + + // }}} + + // {{{ dieGracefully() + + /** + * Gracefully exit from the script when an unrecoverable error is created + * + * @param string $msg Message to display to user + * @param mixed $e Error object + * @param boolean $moreInfo More debugging info when in development + * + * @return void + * @access public + */ + public function dieGracefully($msg = null, $e = null, $moreInfo = false) + { + if (is_null($e)) { + if (is_null($msg)) { + die('There was an error, please try again later!'); + } else { + die($msg); + } + } else { + echo $msg . '
    '; + echo 'Error Caught.
    '; + echo 'Error: ' . $e->getMessage() . '
    '; + if ($moreInfo) { + echo 'Code:
    ' . $e->getCode() . '

    '; + echo 'Debug Info:
    ' . $e->getDebugInfo() . '

    '; + } + } + } + + // }}} + + // {{{ errorException() + + /** + * Stops script on Exception error + * + * Stops the script when an Exception is raised inside a + * try/catch block. + * + * When a site is no longer in DEVELOPMENT, ie: its live on ws3. + * We don't show any error info, but let the user know an unexpected + * error has occured and then mail the error info the the admin. + * + * Example usage: + * + * try { + if ($foo != $bar) { + throw new Exception ("Foo Doesn't equal Bar"); + } + * } catch (Exception $e) { + * return Toolkit_Common::handleError($e); + * } + * + * + * @param Exception $e Exception Object + * @param Mail $mail What to use to send mail to admin + * + * @return false + * @access public + * @static + */ + public static function errorException(Exception $e, Mail $mail = null) + { + if (!is_null($mail)) { + $subject = 'Exception Error for ' . SITENAME; + self::mailError($mail, $subject); + } else { + echo self::getErrorInfo($e); + } + + return false; + } + + // }}} + // {{{ errorHTMLQuickFormError() + + /** + * Handles PEAR Errors for our developers + * + * When a site is no longer in DEVELOPMENT, ie: its live on ws3. + * We don't show any error info, but let the user know an unexpected + * error has occured and then mail the error info the the admin. + * + * HTML_QuickForm Example usage: + * + * $e =& $this->getElement('elementName'); + * if (PEAR::isError($e)) { + * return Toolkit_Common::handleError($e); + * } + * + * + * @param HTML_QuickForm_Error $e QuickFormError Object + * @param Mail $mail What to use to send mail to admin + * + * @return false + * @access public + * @since Method available since Release 1.0.1 + * @static + */ + public static function errorHTMLQuickFormError( + HTML_QuickForm_Error $e, + Mail $mail = null + ) { + if (!is_null($mail)) { + $subject = 'PEAR Error for ' . SITENAME; + self::mailError($mail, $subject); + } else { + echo self::getErrorInfo($e); + } + + return false; + } + + // }}} + // {{{ errorPDOException() + + /** + * Stops script on database error + * + * Stops the script when a PDOException is raised inside a + * try/catch block. + * + * When a site is no longer in DEVELOPMENT, ie: its live on ws3. + * We don't show any error info, but let the user know an unexpected + * error has occured and then mail the error info the the admin. + * + * Example usage: + * + * try { + * $sql = " + * SELECT * + * FROM table_name + * WHERE id = :id"; + * + * $stmt = $this->dbh->prepare($sql); + * $stmt->bindParam(':id', $id, PDO::PARAM_INT); + * return $stmt->execute(); + * } catch (PDOException $e) { + * return Toolkit_Common::handleError($e); + * } + * + * + * @param PDOException $e PDO Error Object. + * @param Mail $mail Mail object used to send admin email + * + * @return false + * @access public + * @since Method available since Release 1.0.1 + */ + public function errorPDOException(PDOException $e, Mail $mail = null) + { + if (!is_null($mail)) { + $subject = 'SQL Error for ' . SITENAME; + self::mailError($mail, $subject); + } else { + echo self::getErrorInfo($e); + } + + return false; + } + + // }}} + // {{{ errorPEARError() + + /** + * Handles PEAR Errors for our developers + * + * When a site is no longer in DEVELOPMENT, ie: its live on ws3. + * We don't show any error info, but let the user know an unexpected + * error has occured and then mail the error info the the admin. + * + * @param PEAR_Error $e PEARError Object + * @param Mail $mail Mail object used to send admin email + * + * @return false + * @access public + * @since Method available since Release 1.0.1 + */ + public function errorPEARError(PEAR_Error $e, Mail $mail = null) + { + if (!is_null($mail)) { + $subject = 'PEAR Error for ' . SITENAME; + self::mailError($mail, $subject); + } else { + echo self::getErrorInfo($e); + } + + return false; + } + + // }}} + // {{{ errorRuntimeException() + + /** + * Stops script on runtime error + * + * Stops the script when a runtimeException is raised inside a + * try/catch block. + * + * When a site is no longer in DEVELOPMENT, ie: its live on ws3. + * We don't show any error info, but let the user know an unexpected + * error has occured and then mail the error info the the admin. + * + * @param RuntimeException $e PDO Error Object. + * @param Mail $mail Mail object used to send admin email + * + * @return false + * @access public + * @since Method available since Release 1.0.2 + */ + public function errorRuntimeException( + RuntimeException $e, + Mail $mail = null + ) { + if (!is_null($mail)) { + $subject = 'Runtime Exception for ' . SITENAME; + self::mailError($mail, $subject); + } else { + echo self::getErrorInfo($e); + } + + return false; + } + + // }}} + // {{{ errorBadMethodCallException() + + /** + * Stops script on bad method call error + * + * Stops the script when a badMethodCallException is raised inside a + * try/catch block. + * + * When a site is no longer in DEVELOPMENT, ie: its live on ws3. + * We don't show any error info, but let the user know an unexpected + * error has occured and then mail the error info the the admin. + * + * @param BadMethodCallException $e PDO Error Object. + * @param Mail $mail Mail object used to send admin email + * + * @return false + * @access public + * @since Method available since Release 1.0.3 + */ + public function errorBadMethodCallException( + BadMethodCallException $e, + Mail $mail = null + ) { + if (!is_null($mail)) { + $subject = 'Bad Method Call Exception for ' . SITENAME; + self::mailError($mail, $subject); + } else { + echo self::getErrorInfo($e); + } + + return false; + } + + // }}} + + // {{{ filterURI() + + /** + * Filters uri's before they are validated + * + * @param string $uri URI to filter + * + * @return mixed new uri if missing scheme + * @access public + * @static + */ + public static function filterURI($uri) + { + $validProtocol = '/^https?\:\/\/.*/'; + $invalidProtocol = '/^.*?\:\/\/.*/'; + if (empty($uri)) { + // Empty field, just return + return $uri; + } elseif (preg_match($validProtocol, $uri)) { + // has valid protocol, return unchanged + // should pass validation. + return $uri; + } elseif (!preg_match($invalidProtocol, $uri)) { + // missing protocol, prepend default + // http:// protocol and return. + return "http://$uri"; + } else { + // has invalid protocol, return unchanged + // validation should catch this and throw error. + return $uri; + } + } + + // }}} + // {{{ filterPhone() + + /** + * Filters phone numbers before they are validated + * + * @param string $phone number to filter + * + * @return mixed newly formatted phone number + * @access public + * @static + */ + public static 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; + } + + // }}} + + // {{{ getCities() + + /** + * Get an array of cities from the database + * + * @param PDO $dbh Database handler + * @param integer $state State id the city is in + * @param integer $county County id the city is in + * @param integer $region Region id the city is in + * + * @return array states + * @access public + * @static + */ + public static function getCities( + PDO $dbh, + $state = null, + $county = null, + $region = null + ) { + $param = array(); + if (ctype_digit((string)$state)) { + $param[] = 'state_id = ' . $dbh->quote($state); + } + if (ctype_digit((string)$county)) { + $param[] = 'county_id = ' . $dbh->quote($county); + } + if (ctype_digit((string)$region)) { + $param[] = 'region_id = ' . $dbh->quote($region); + } + + try { + $sql = " + SELECT * + FROM city"; + + if (!empty($params)) { + $sql .= ' WHERE ' . implode(' AND ', $params); + } + $sql .= ' ORDER BY city_name'; + + $stmt = $dbh->prepare($sql); + $stmt->execute(); + + $cities = array(); + while ($row = $stmt->fetch()) { + $cities[$row['city_id']] = $row['city_name']; + } + + return $cities; + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + // {{{ getErrorInfo() + + /** + * extract error info from error object + * + * @param mixed $obj Error object to get info for + * + * @return string formatted error information + * @access public + */ + public function getErrorInfo($obj) + { + $state = '' . get_class($obj) . ' error: '; + + if (method_exists($obj, 'getMessage')) { + $state .= $obj->getMessage(); + if (method_exists($obj, 'getDebugInfo')) { + $state .= '; ' . $obj->getDebugInfo(); + } + } + if (method_exists($obj, 'getFile')) { + $state .= ' in ' . $obj->getFile() . ''; + } + if (method_exists($obj, 'getLine')) { + $state .= ' on line ' . $obj->getLine() . ''; + } + $state .= '
    $_SERVER[\'QUERY_STRING\']: ' . $_SERVER['QUERY_STRING'] . "\n"; + $state .= '
    $_GET:
    ' . print_r($_GET, true) . '
    '; + $state .= '
    $_POST:
    ' . print_r($_POST, true) . '
    '; + /* + if (method_exists($obj, 'getBacktrace')) { + $backtrace = print_r($obj->getBacktrace(), true); + + $state .= "
    $backtrace
    "; + } + */ + + return $state; + } + + // }}} + // {{{ getHierarchicalTreeStructure() + + /** + * Create a hierarchical tree stored in an linear array + * + * Produces a representation of a hierarchical tree structure into a + * linear array so you can iterate straight through to get the tree + * structure. + * + * @param PDO $pdo Database handler + * @param string $table Name of the source relation + * @param string $key Name of the key field + * @param string $parent Name of the parent-key field + * @param string $order Name of the field to order siblings by + * @param integer $start Key value of the row to start at + * @param integer $maxDepth Maximum depth to descend to, or zero + * for unlimited depth + * @param boolean $validParent exclude branches that have null + * parent values + * + * @return array Linear array of tree structure + * @access public + * @see http://www.postgresql.org/doc/8.3/interactive/tablefunc.html#AEN104085 + */ + public function getHierarchicalTreeStructure( + PDO $pdo, + $table = 'bus_category', + $key = 'id', + $parent = 'parent', + $order = 'pos', + $start = 0, + $maxDepth = 0, + $validParent = true + ) { + try { + $tree = array(); + + $sql = " + SELECT * + FROM connectby('$table', '$key', '$parent', + '$order', '$start', $maxDepth) + as t(id text, parent text, level int, pos int)"; + + if ($validParent) { + $sql .= " WHERE parent is not null"; + } + foreach ($pdo->query($sql) as $row) { + $tree[$row['id']] = $row['level']; + } + + return $tree; + } catch (PDOException $e) { + return self::handleError($e); + } + } + + // }}} + // {{{ scriptsCompare() + + /** + * make sure jquery lib is loaded first + * + * @param string $i script 1 to compare against script 2 ($j) + * @param string $j script 2 to compare against script 1 ($i) + * + * @return integer result of comparison + * @access public + * @static + */ + public static function scriptsCompare($i, $j) + { + if ($i == GLM_APP_BASE_URL . 'libjs/jquery-1.3.2.min.js') { + return -1; + } elseif ($j == GLM_APP_BASE_URL . 'libjs/jquery-1.3.2.min.js') { + return 1; + } else { + return 0; + } + } + + // }}} + // {{{ getScripts() + + /** + * Gets all scripts for the page + * + * @return string HTML markup for scripts + * @access public + * @static + */ + public static function getScripts() + { + if ( !isset($GLOBALS['scripts']) + || !is_array($GLOBALS['scripts']) + || empty($GLOBALS['scripts']) + ) { + return false; + } + + $uniqueScripts = array_unique($GLOBALS['scripts']); + usort($uniqueScripts, array(self, 'scriptsCompare')); + $format = ''; + + $ret = ''; + foreach ($uniqueScripts as $v) { + $ret .= sprintf($format, $v) . "\n"; + } + + return $ret; + } + + // }}} + // {{{ getStates() + + + /** + * Get an array of states from the database + * + * @param PDO $dbh Database handler + * @param boolean $unionStatesOnly If we want to only retrieve + * the 50 US states + * + * @return array states + * @access public + * @static + */ + public static function getStates(PDO $dbh, $unionStatesOnly = false) + { + if ($unionStatesOnly) { + // Just grab the 50 states of the union + $where = "WHERE us_state = :bool"; + } + + try { + $sql = " + SELECT * + FROM state + $where + ORDER BY state_name"; + + $stmt = $dbh->prepare($sql); + if ($unionStatesOnly) { + $stmt->bindValue(':bool', 1, PDO::PARAM_BOOL); + } + $stmt->execute(); + + $states = array(); + while ($row = $stmt->fetch()) { + $states[$row['state_id']] = $row['state_name']; + } + + return $states; + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + // {{{ getStyleSheets() + + /** + * Gets all style sheets for the page + * + * @return string HTML markup for stylesheets + * @access public + * @static + */ + public static function getStyleSheets() + { + if ( !isset($GLOBALS['styleSheets']) + || !is_array($GLOBALS['styleSheets']) + || empty($GLOBALS['styleSheets']) + ) { + return false; + } + + $uniqueStyleSheets = array_unique($GLOBALS['styleSheets']); + $format = ''; + + $ret = ''; + foreach ($uniqueStyleSheets as $v) { + $ret .= sprintf($format, $v) . "\n"; + } + + return $ret; + } + + // }}} + // {{{ getTableMetaData() + + /** + * Gets the meta data of the calling classes table columns + * + * The table used when retrieving the meta data is defined + * in the class property $tableName. The class or parent class + * must also have a $tableMetaData property + * + * @param PDO $pdo Database Handler + * @param string $tableName The name of the table to get the meta data for. + * @param array $clauses Only retrieve meta data for certain column types + * + * @return array metadata for table + * @access protected + */ + public function getTableMetaData( + PDO $pdo, + $tableName, + array $clauses = null + ) { + if (is_array($clauses)) { + while ($c = current($clauses)) { + $ands .= " data_type = '{$c}'"; + if (false !== next($clauses)) { + $ands .= " OR "; + } + } + $ands = " AND ($ands)"; + } + try { + $sql = " + SELECT column_name, data_type + FROM information_schema.columns + WHERE table_name = :tname + $ands"; + $stmt = $pdo->prepare($sql); + $stmt->bindParam(':tname', $tableName, PDO::PARAM_STR); + + $stmt->execute(); + + $metaData = array(); + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + $metaData[$row['column_name']] = $row['data_type']; + } + + return $metaData; + } catch (PDOException $e) { + return self::handleError($e); + } + } + + // }}} + + // {{{ handleError() + + /** + * Handles various script error + * + * @param Object $e Error Object + * @param boolean $developmentServer If we are on a development server + * + * @return false + * @access public + * @static + */ + public static function handleError($e, $developmentServer = DEVELOPMENT) + { + $errorType = str_replace('_', '', get_class($e)); + $errorType = "error$errorType"; + + if (method_exists(__CLASS__, $errorType)) { + if (!$developmentServer) { + // Tell the user we encountered an Error. + include_once BASE . "404.html"; + + $mail = Mail::factory('mail'); + self::$errorType($e, $mail); + exit(); + } else { + return self::$errorType($e, $mail); + } + } else { + echo '

    The system has encountered an un-recoverable error!

    '; + } + } + + // }}} + + // {{{ mailError() + + /** + * Mails the error to the site admin + * + * @param Mail $mail Mail object to use + * @param string $subject Subject of email + * + * @return void + * @access public + * @static + */ + public static function mailError(Mail $mail, $subject) + { + $msg = '

    ' . self::getErrorInfo($e) . '

    '; + + $htmlMsg = "$msg"; + $crlf = "\n"; + $mimeMail = new Mail_mime($crlf); + $mimeMail->setFrom(self::$from); + $mimeMail->setSubject($subject); + $mimeMail->setHTMLBody($htmlMsg); + $mimeMail->setTXTBody($msg); + + $body = $mimeMail->get(); + $headers = $mimeMail->headers(); + + $mail->send(self::$admin, $headers, $body); + } + + // }}} + // {{{ multiDimArrayLocate() + + /** + * Locates an array value in a multi-dimensional array + * + * @param array $array The Array which holds the value you need. + * @param mixed $text The value that you are looking for. + * + * @return mixed The search result. + */ + public function multiDimArrayLocate($array, $text) + { + if (!is_array($array)) { + return; + } + + foreach ($array as $k => $v) { + if (is_array($v)) { + $temp[$k] = self::multiDimArrayLocate($v, $text); + if ($temp[$k]) { + $arrayResult[$k] = $temp[$k]; + } + } else { + if ($v == $text) { + $arrayResult[$k] = $v; + } + } + } + return $arrayResult; + } + + // }}} + + // {{{ processQuery() + + /** + * Performs the sql insert statement + * + * If using a Postgresql driver for the PDO, metadata is used when + * binding parameters to the prepared statement. + * + * @param object $dbh Database handler object + * @param string $tableName table used in query + * @param string $sql sql query string + * @param array $values associative array of key/value pairs that will + * be used to bind to the sql query string + * + * @return boolean result of the execute statement on the database + * @access public + * @static + */ + public static function processQuery( + PDO $dbh, + $tableName, + $sql, + array $values = null + ) { + $dbType = $dbh->getAttribute(PDO::ATTR_DRIVER_NAME); + if ($dbType == 'pgsql') { + $md = Toolkit_Common::getTableMetaData($dbh, $tableName); + } + $stmt = $dbh->prepare($sql); + foreach ($values as $k => &$v) { + if ($dbType == 'pgsql') { + $metaData = $md[$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. + // as empty values '', are not considered unique + if ( empty($v) + && $dataType !== PDO::PARAM_BOOL + && $dataType !== PDO::PARAM_INT + ) { + $v = null; + $dataType = PDO::PARAM_NULL; + } + $stmt->bindParam(":$k", $v, $dataType); + } else { + $stmt->bindParam(":$k", $v); + } + } + + return $stmt->execute(); + } + + // }}} + + // {{{ recursiveArraySearch() + + /** + * Recursive multi-dimensional array search + * + * @param string $n Needle + * @param array $h Haystack + * + * @return mixed search result - false if not found + * @access public + * @static + */ + public static function recursiveArraySearch($n, array $h) + { + foreach ($h as $i => $j) { + $curr = $i; + if ($n === $j + || (is_array($j) && self::recursiveArraySearch($n, $j) !== false) + ) { + return $curr; + } + } + + return false; + } + + // }}} + + // {{{ show() + + /** + * Renders the calling class to the screen + * + * @access public + * @return string calls the toHTML function of calling class + */ + public function show() + { + echo $this->toHTML(); + } + + // }}} +} +?> diff --git a/Toolkit/Contacts/BrochureRequest.php b/Toolkit/Contacts/BrochureRequest.php new file mode 100755 index 0000000..c8eb6b7 --- /dev/null +++ b/Toolkit/Contacts/BrochureRequest.php @@ -0,0 +1,139 @@ + + * @copyright 2009 Jamie Kahgee + * @license http://www.gaslightmedia.com Gaslightmedia + * @version CVS: $Id: BrochureRequest.php,v 1.5 2010/01/28 16:34:53 jamie Exp $ + * @link <> + * @see References to other sections (if any)... + */ + +/** + * Short description for class + * + * Long description (if any) ... + * + * @category Contacts + * @package Toolkit_Contacts + * @author Jamie Kahgee + * @copyright 2009 Jamie Kahgee + * @license http://www.gaslightmedia.com Gaslightmedia + * @version Release: @package_version@ + * @link <> + * @see References to other sections (if any)... + */ +class Toolkit_Contacts_BrochureRequest +{ + // {{{ Class Properties + /** + * the name of the brochure download file + * @var unknown + * @access protected + */ + protected $pdfFile; + + /** + * template for brochure + * @var string + * @access protected + */ + protected $template = 'brochurePage.html'; + + /** + * name of the brochure + * @var unknown + * @access protected + */ + protected $brochureName; + // }}} + // {{{ __construct() + /** + * Class constructor + * + * @param object $pdo PHP Data Object + * + * @return void + * @access public + */ + function __construct(PDO $pdo) + { + $this->brochureName = SITENAME.' Brochure'; + $this->dbh = $pdo; + } + // }}} + // {{{ show() + /** + * call toHtml + * + * @return void + * @access public + */ + function show() + { + echo $this->toHtml(); + } + // }}} + // {{{ toHtml() + /** + * create HTML output + * + * @return object html + * @access public + */ + function toHtml() + { + $options = $GLOBALS['flexyOptions']; + $options['templateDir'] = BASE.'Toolkit/Contacts/templates'; + $options['compileDir'] = BASE.'Toolkit/Contacts/templates/compiled'; + $tpl = new HTML_Template_Flexy($options); + + $page = new StdClass; + $page->brochure = $this->brochureName; + + // set the pdf form + $pdfForm = new Toolkit_Contacts_PdfForm( + 'pdf_form', + 'post', + null, + null, + null, + true + ); + + $page->pdfForm = $pdfForm->toHtml(); + + // set the contact form + $contactForm = new Toolkit_Contacts_ContactUs( + $this->dbh, + 'contact', + 'post', + null, + null, + null, + true + ); + + $contactForm->subject = 'Brochure Request from demo site'; + $contactForm->configureForm(); + $contactForm->useCaptcha(true); + $page->contactForm = $contactForm->toHtml(); + + if ($pdfForm->sent) { + $page->contactForm = ''; + } elseif ($contactForm->sent) { + $page->pdfForm = ''; + } + + $tpl->compile($this->template); + return $tpl->bufferedOutputObject($page); + } + // }}} +} +?> diff --git a/Toolkit/Contacts/ContactUs.php b/Toolkit/Contacts/ContactUs.php new file mode 100755 index 0000000..824f31d --- /dev/null +++ b/Toolkit/Contacts/ContactUs.php @@ -0,0 +1,1110 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @version CVS: $Id: ContactUs.php,v 1.30 2010/01/28 16:33:01 jamie Exp $ + * @link http://demo.gaslightmedia.com + */ + +/** + * Error codes for Toolkit_Contacts_ContactUs + * + * Codes are mapped to textual messaged by errorMessage() method, + * if you add a new code be sure to add a new message for it to errorMessage() + * + * @see Toolkit_Contacts_ContactUs::errorMessage() + */ +define('FORM_OK', 1); +define('FORM_ERROR', -1); +define('NO_RECORD', -2); +define('INVALID_DB', -3); +define('MISSING_CONSTANT', -4); +define('MISSING_CONTACT_TYPE', -5); + +/** + * GLM Contact Us form + * + * This form handles rendering and processing the contact us form. + * Controls the email functionality of the form, whether the client + * has a contact DB to store contact records and how to insert/update + * submitted form values. + * + * @category Contacts + * @package Toolkit_Contacts + * @author Jamie Kahgee + * @copyright 2009 Jamie Kahgee + * @license http://www.gaslightmedia.com Gaslightmedia + * @link http://demo.gaslightmedia.com + * @see Toolkit_FormBuilder + */ +class Toolkit_Contacts_ContactUs + extends Toolkit_FormBuilder implements Toolkit_Form +{ + // {{{ properties + + /** + * Table in Database which holds the contact data + * + * @var string + * @access public + */ + public $tableName = 'contact'; + + /** + * 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 = array(); + + /** + * Contact type to be inserted into the DB as when the form is submitted + * + * This property is only valid when the [hasContactDB] property is set + * to true. + * + * N.B. + * If you subclass this class out to other forms that are + * inserted into the contact db, be sure to make each one of their + * contactType properties unique. We don't check for duplicates. + * + * @var string + * @access protected + */ + protected $contactType = '1'; + + /** + * 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 string + * @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 string + * @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 + */ + public $subject; + + /** + * Whether the site has a contact DB to store contact records + * + * If this value is set to false, an email will still be sent to the + * addressed specified in the email property. + * + * @var boolean + * @access protected + */ + protected $hasContactDB = true; + + /** + * The interests from the contact db + * + * @var array + * @access protected + */ + protected $inquiries = array(); + + /** + * Message to display if the form is successfully submitted + * + * @var string + * @access protected + */ + protected $successMsg = ' +
    + Thank you for your questions or comments! +
    '; + + /** + * 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 + * @see app.gaslightmedia.com/glmPEAR/HTML/QuickForm/Rules/Zip.php + */ + protected $registeredRules = array( + 'zip', + 'phone', + array( + 'checkEmail', + 'callback', + 'email', + '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 object $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 + * + * @author Jamie Kahgee + * @access public + * @link http://pear.php.net/package/HTML_QuickForm/docs/latest/HTML_QuickForm/HTML_QuickForm.html + * @see HTML_QuickForm + */ + public function __construct( + PDO $pdo, + $formName, + $method = 'post', + $action = '', + $target = '', + $attributes = null, + $trackSubmit = false + ) { + // Make sure these end cases are never met. + // These are more for the development phase. + if ($this->email === false && $this->hasContactDB === false) { + PEAR::raiseError( + null, + NO_RECORD, + PEAR_ERROR_CALLBACK, + array(&$this, 'error') + ); + } + if (!is_bool($this->hasContactDB)) { + PEAR::raiseError( + null, + INVALID_DB, + PEAR_ERROR_CALLBACK, + array(&$this, 'error') + ); + } + // we haven't defined the FROM_NEWS_EMAIL constant and + // the email will default to relying on it. + if ( !defined('FROM_NEWS_EMAIL') + && (empty($this->email) && $this->email !== false) + ) { + PEAR::raiseError( + 'You need to define the FROM_NEWS_EMAIL + constant for this form to work correctly', + MISSING_CONSTANT, + PEAR_ERROR_CALLBACK, + array(&$this, 'error') + ); + } + if (!is_numeric($this->contactType) && $this->hasContactDB) { + PEAR::raiseError( + null, + MISSING_CONTACT_TYPE, + PEAR_ERROR_CALLBACK, + array(&$this, 'error') + ); + } + parent::__construct( + $formName, + $method, + $action, + $target, + $attributes, + $trackSubmit + ); + + $this->dbh = $pdo; + + // Default Renderer Form templates for QuickForm in respect to this + // classes needs. + 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; + } + + /** + * Where are the flexy templates stored at for this class. + */ + define('TEMPLATES_DIR', BASE . 'Toolkit/Contacts/templates'); + + /** + * Where are the compiled flexy templates stored at for this class. + */ + define('COMPILED_DIR', BASE . 'Toolkit/Contacts/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; + + $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' => 20, + 'font_path' => GLM_APP_BASE . 'glmPEAR/Image/Canvas/Fonts/', + 'font_file' => 'times.ttf', + 'background_color' => '#cccccc', + 'obfuscation' => false, + 'angle' => true, + ), + ); + } + + // }}} + + // {{{ configureConstats() + + /** + * Constant variables for the form + * + * These values won't get overridden by POST or GET vars + * + * @return void + * @access public + */ + public function configureConstants() + { + $constants = array( + 'user_agent' => $_SERVER['HTTP_USER_AGENT'], + 'remote_addr' => $_SERVER['REMOTE_ADDR'], + ); + $this->setupConstants($constants); + } + + // }}} + // {{{ configureDefaults() + + /** + * Initializes default form values + * + * @return void + * @access public + */ + public function configureDefaults() + { + $defaults = array( + 'state' => '', + 'mail_ok' => 1 + ); + + $this->setupDefaults($defaults); + } + + // }}} + // {{{ configureElements() + + /** + * Form element definitions + * + * @return void + * @access public + */ + public function configureElements() + { + $e = array(); + $this->setInterestFields(); + // Grouped Elements are defined here. + $this->interestsGroups =& $this->getInterestFields(); + + // All Elements are created here. This includes group element definitions. + $e[] = array( + 'type' => 'hidden', + 'req' => false, + 'name' => 'user_agent' + ); + $e[] = array( + 'type' => 'hidden', + 'req' => false, + 'name' => 'remote_addr' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'fname', + 'display' => 'First Name' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'lname', + 'display' => 'Last Name' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'address', + 'display' => 'Address 1' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'address2', + 'display' => 'Address 2' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'city', + 'display' => 'City' + ); + $e[] = array( + 'type' => 'select', + 'req' => false, + 'name' => 'state', + 'display' => 'State/Province', + 'opts' => $GLOBALS['states'] + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'zip', + 'display' => 'ZIP/Postal Code' + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'email', + 'display' => 'Email' + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'email_rmv', + 'display' => 'Verify Email' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'phone', + 'display' => 'Phone' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'fax', + 'display' => 'Fax' + ); + $e[] = array( + 'type' => 'textarea', + 'req' => false, + 'name' => 'comments', + 'display' => 'Comments' + ); + $e[] = array( + 'type' => 'advcheckbox', + 'req' => false, + 'name' => 'mail_ok', + 'display' => 'Yes, I would like to receive Email Newsletters', + 'opts' => 'Yes', + 'val' => array(0, 1) + ); + if (is_array($this->interestsGroups)) { + foreach ($this->interestsGroups as $group => $gData) { + $this->myGroups[] = $gData; + $e[] = array( + 'type' => 'group', + 'req' => false, + 'name' => 'interest['.$group.']', + 'group' => $gData, + 'label' => $group, + 'seperator' => ' ', + 'appendName' => true + ); + } + } + $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 Form' + ); + + $this->setupElements($e); + } + + // }}} + // {{{ configureRules() + + /** + * Form rule definitions + * + * Adds validation rules for the given fields + * + * @return void + * @access public + */ + public function configureRules() + { + $r = array(); + // Form Rules + $r[] = array( + 'element' => array('email', 'email_rmv'), + 'message' => 'ERROR: Your Email Addresses Do Not Match!', + 'type' => 'compare', + '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' => 'state', + 'message' => 'ERROR: Invalid State!', + 'type' => 'numeric', + 'format' => null, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + */ + $r[] = array( + 'element' => 'phone', + 'message' => 'ERROR: Invalid number (xxx) xxx-xxxx!', + 'type' => 'phone', + 'format' => null, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + $r[] = array( + 'element' => 'fax', + 'message' => 'ERROR: Invalid number (xxx) xxx-xxxx!', + 'type' => 'phone', + 'format' => null, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + $r[] = array( + 'element' => 'zip', + 'message' => 'ERROR: Invalid Zip!', + 'type' => 'zip', + 'format' => array('requireDBCheck' => false), + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + $r[] = array( + 'element' => 'mail_ok', + 'message' => 'ERROR: Invalid Value!', + 'type' => 'numeric', + 'format' => null, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + $r[] = array( + 'element' => 'captcha_rmv', + 'message' => 'ERROR: Incorrect verification code!', + 'type' => 'CAPTCHA', + 'format' => $this->captchaQuestion, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + + $this->setupRules($r); + } + + // }}} + // {{{ 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, configures the entire form + * + * @return void + * @access public + */ + public function configureForm() + { + $this->configureElements(); + $this->configureFilters(); + $this->configureRules(); + $this->configureDefaults(); + $this->configureConstants(); + } + + // }}} + // {{{ contactExists() + + /** + * Checks for a duplicate email address already in the DB. + * + * @param string $email The email address to check for in the DB + * + * @return boolean If the email address already exists + * @access protected + */ + protected function contactExists($email) + { + // Check if a contact w/ the submitted email already exists. + // if so, then we need to update, if not then do a fresh insert. + try { + $sql = " + SELECT count(*) AS count + FROM {$this->tableName} + WHERE email = :email"; + + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(':email', $email, PDO::PARAM_STR); + $stmt->execute(); + $stmt->bindColumn('count', $contactExists); + $stmt->fetch(); + + return (bool) $contactExists; + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + + // {{{ 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. + * + * @param string $mailFactory What type of mail factory should we use + * + * @return boolean result of the mailing + * @access protected + */ + protected function emailOwner($mailFactory = 'mail') + { + if (!$this->email) { + return; + } + + $hasInterestField = $this->elementExists('interest'); + + $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')); + + $page->email_from = OWNER_EMAIL; + $page->subject = $this->subject; + $page->client_info = $this->clientInfo; + $page->fname = $this->getSubmitValue('fname'); + $page->lname = $this->getSubmitValue('lname'); + $page->formData = $this->formData; + + if ($hasInterestField) { + // Clean up the interests so they will look nice in the email + $page->formData['interest']['nowrap'] = 'nowrap'; + $page->formData['interest']['element'] = null; + + $g =& $this->getElement('interest'); + $ge =& $g->getElements(); + + $interests = array(); + foreach ($ge as $e) { + if ($e->getChecked()) { + $interests[] = $e->getText(); + } + } + $page->formData['interest']['element'] = implode('
    ', $interests); + } + + if ($this->elementExists('mail_ok')) { + // Clean up the mail_ok flag so its human readable + $page->formData['mail_ok']['element'] + = ($page->formData['mail_ok']['element']) ? 'Yes' : 'No'; + } + + $template->compile('emailOwner.tpl'); + $htmlMsg = $template->bufferedOutputObject($page); + + if ($hasInterestField) { + // Text version can't have HTML in it + // so reset the interests to use commas + $page->formData['interest']['element'] = implode(", ", $interests); + } + $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"; + } + + $mimeMail = new Mail_mime("\n"); + $mimeMail->setFrom("Online Form <{$page->email_from}>"); + $mimeMail->setSubject($this->subject); + $mimeMail->setHTMLBody($htmlMsg); + $mimeMail->setTXTBody($msg); + + $mail =& Mail::factory($mailFactory); + $body = $mimeMail->get(); + + $setHeader['Reply-To'] = "{$this->getSubmitValue('fname')} {$this->getSubmitValue('lname')} <{$this->getSubmitValue('email')}>"; + + $headers = $mimeMail->headers($setHeader); + + $res = $mail->send($this->email, $headers, $body); + if (PEAR::isError($res)) { + return Toolkit_Common::handleError($res); + } else { + return $res; + } + } + + // }}} + // {{{ error() + + /** + * Display errors with the form to the user + * + * @param object $error PEAR Error Object + * + * @return void + * @access public + */ + public function error($error) + { + // make the variables static so that is only has to do the defining + // on the first call. + static $errorMessages; + static $className; + + // define the various error messages + if (!isset($errorMessages)) { + $className = get_class($this); + $errorMessages = array( + FORM_OK => 'No error', + FORM_ERROR => 'Unknown error', + NO_RECORD => 'Setting both properties (email and hasContactDB) to false in the ' . $className . ' class will result in no email record being sent and no record being inserted into the database. There will be no record that this form was ever filled out.', + INVALID_DB => 'Please set the property hasContactDB to a boolean value in the class ' . $className . ' before continuing', + MISSING_CONSTANT => 'You have failed to set a CONSTANT for the class ' . $className . ' to function properly', + MISSING_CONTACT_TYPE => 'Please set the property contactType in the class '. $className . ' before continuing',); + } + + if (!is_null($error->message)) { + $message = $error->message; + } elseif (isset($errorMessages[$error->code])) { + $message = $errorMessages[$error->code]; + } else { + $message = $errorMessages[$error->code]; + $message = $errorMessages[FORM_ERROR]; + } + + echo "
    {$message}
    "; + } + + // }}} + + // {{{ getInterestFields() + + /** + * Returns the field definitions of the contact db interest fields + * + * @return array Group definitions for the interest fields + * @access protected + */ + protected function getInterestFields() + { + if (is_array($this->inquiries)) { + foreach ($this->inquiries as $group => $data) { + foreach ($data as $k => $v) { + $interests[$group][] = array('type' => 'checkbox', + 'req' => false, + 'name' => $k, + 'opts' => $v); + } + } + } + + return $interests; + } + + // }}} + + // {{{ 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) + { + unset($values['comments']); + $values['contact_type'] = ":{$this->contactType}:"; + if (is_array($values['interest']) && !empty($values['interest'])) { + foreach ($values['interest'] as $iGroup => $interests) { + $newInterest[] = implode(':', array_keys($interests)); + } + if (is_array($newInterest)) { + $values['interest'] = ':' . implode(':', $newInterest) . ':'; + } + } + try { + $sql = Toolkit_Common::createSQLInsert( + $this->tableName, + array_keys($values) + ); + + return Toolkit_Common::processQuery( + $this->dbh, + $this->tableName, + $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( + 'user_agent', + 'remote_addr', + 'contact_type', + ); + $this->setFormData($e); + + + // If no contact db, return true so we can send owner email. + if (!$this->hasContactDB) { + return true; + } + + // Get rid of any elements in the values array that + // aren't going to be used when inserting/updating the db. + $values = Toolkit_Common::cleanArray($values); + + // Send data off to StreamSend + if ( defined('STREAMSEND_FORMS_API') + && STREAMSEND_FORMS_API + && $values['mail_ok'] + ) { + // Insert the record into the streamsend server + $streamSend = new Toolkit_Contacts_StreamSend(); + $streamSend->addContact($values); + } + + // Check if we are updating an existing contact or not + // question: is this the best approach? what if someone else + // sends a form through w/ different data but the same emil addy + // the old users data can be completely wiped out. + $existingContact = $this->contactExists($values['email']); + + if ($existingContact) { + return $this->updateData($values); + } else { + return $this->insertData($values); + } + } + + // }}} + + // {{{ setInterestFields() + + /** + * Contact DB interests + * + * @return void + * @access protected + */ + protected function setInterestFields() + { + try { + $sql = " + SELECT contact_inq.*, inq_group.name + FROM contact_inq LEFT OUTER JOIN inq_group ON (contact_inq.groupid = inq_group.id) + ORDER BY groupid, pos"; + + $i = array(); + foreach ($this->dbh->query($sql) as $row) { + $i[$row['name']][$row['id']] = $row['header']; + } + + $this->inquiries = $i; + } catch (PDOException $e) { + Toolkit_Common::handleError($e); + } + } + + // }}} + // {{{ setupRenderers() + // @codeCoverageIgnoreStart + + /** + * 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}', 'interest'); + if (is_array($this->interestsGroups)) { + foreach ($this->interestsGroups as $group => $gData) { + $renderer->setGroupTemplate('
    {content}', 'interest['.$group.']'); + $renderer->setGroupElementTemplate('{element}', 'interest['.$group.']'); + $renderer->setElementTemplate(''.$required.'{label}'.$error.'{element}', 'interest['.$group.']'); + } + } + $renderer->setElementTemplate(''.$required.'{label}'.$error.'{element}', 'comments'); + $renderer->setElementTemplate(''.$required.'{label}'.$error.'{element}', 'submit_rmv'); + + $renderer->setElementTemplate('{element}', 'captcha_question'); + $renderer->setElementTemplate(''.$required.''.$error.'{element}What is this?', 'captcha_rmv'); + } + + // @codeCoverageIgnoreEnd + // }}} + // {{{ toHtml() + + /** + * Handles how to display the current step the user is at in the form + * + * destroying and resetting the captcha value dis-allows someone from + * re-sending a form on a previous captcha. + * + * @return string form HTML state + * @access public + */ + public function toHtml() + { + $this->setupRenderers(); + if ($this->validate()) { + $this->captchaQuestion->destroy(); + $this->cleanForm(); + + if ($this->process(array(&$this, 'processData'), $this->mergeFiles)) { + $this->freeze(); + $this->emailOwner(); + $output = $this->successMsg; + } + $this->sent = true; + } elseif ($this->isSubmitted()) { + $this->captchaQuestion->destroy(); + $this->captchaAnswer->setValue(''); + $output = $this->errorMsg; + $output .= parent::toHTML(); + } else { + $this->captchaQuestion->destroy(); + $this->captchaAnswer->setValue(''); + $output = parent::toHTML(); + } + return $output; + } + + // }}} + + // {{{ updateData() + + /** + * Updates the contact in the contact db + * + * @param array $values Form submitted values + * + * @return object Result of the update query + * @access protected + */ + protected function updateData($values) + { + unset($values['comments']); + if (is_array($values['interest']) && !empty($values['interest'])) { + foreach ($values['interest'] as $iGroup => $interests) { + $newInterest[] = implode(':', array_keys($interests)); + } + if (is_array($newInterest)) { + $values['interest'] = ':' . implode(':', $newInterest) . ':'; + } + } + + try { + // Get all the existing contact type data + $sql = " + SELECT contact_type + FROM {$this->tableName} + WHERE email = :email"; + + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(':email', $values['email'], PDO::PARAM_STR); + $stmt->execute(); + $stmt->bindColumn('contact_type', $cType); + $stmt->fetch(); + + $existingTypes = explode(':', $cType); + if (!in_array($this->contactType, $existingTypes)) { + $values['contact_type'] = "$cType{$this->contactType}:"; + } + + $sql = Toolkit_Common::createSQLUpdate( + $this->tableName, + array_keys($values), + array('email = :email') + ); + + return Toolkit_Common::processQuery( + $this->dbh, + $this->tableName, + $sql, + $values + ); + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} +} +?> diff --git a/Toolkit/Contacts/PdfForm.php b/Toolkit/Contacts/PdfForm.php new file mode 100755 index 0000000..0d6ff50 --- /dev/null +++ b/Toolkit/Contacts/PdfForm.php @@ -0,0 +1,895 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @version CVS: $Id: PdfForm.php,v 1.9 2010/01/28 16:33:27 jamie Exp $ + * @link http://demo.gaslightmedia.com + */ + +/** + * Error codes for Toolkit_Contacts_PdfForm + * + * Codes are mapped to textual messaged by errorMessage() method, + * if you add a new code be sure to add a new message for it to errorMessage() + * + * @see Toolkit_Contacts_ContactUs::errorMessage() + */ +define('FORM_OK', 1); +define('FORM_ERROR', -1); +define('NO_RECORD', -2); +define('INVALID_DB', -3); +define('MISSING_CONSTANT', -4); + +/** + * GLM Contact Us form + * + * This form handles rendering and processing the contact us form. + * Controls the email functionality of the form, whether the client + * has a contact DB to store contact records and how to insert/update + * submitted form values. + * + * @category Contacts + * @package Toolkit_Contacts + * @author Jamie Kahgee + * @copyright 2009 Jamie Kahgee + * @license http://www.gaslightmedia.com Gaslightmedia + * @link http://demo.gaslightmedia.com + */ +class Toolkit_Contacts_PdfForm extends Toolkit_FormBuilder +{ + // {{{ properties + + /** + * Table in Database which holds the contact data + * + * @var string + * @access public + */ + public $tableName = 'contact'; + + /** + * 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; + + /** + * Used in the email template for the client info string at the bottom + * + * @var string + * @access protected + */ + protected $clientInfo = array( + 'name' => 'Gaslight Media', + 'address' => '120 E. Lake St.', + 'city' => 'Petoskey', + 'state' => 'MI', + 'zip' => '49770', + 'phone' => '231.487.0697', + ); + + /** + * 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; + + /** + * pdfFileName + * + * Just the filename not the path. File needs to be in BASE.'assets/' dir + * + * @var string + * @access protected + */ + protected $pdfFileName = 'brochure.pdf'; + + /** + * Whether the site has a contact DB to store contact records + * + * If this value is set to false, an email will still be sent to the + * addressed specified in the email property. + * + * @var boolean + * @access protected + */ + protected $hasContactDB = true; + + /** + * The interests from the contact db + * + * @var array + * @access protected + */ + protected $inquiries = array(); + + /** + * Message to display if the form is successfully submitted + * + * @var string + * @access protected + */ + protected $successMsg = ' +
    + Thank you for your Request. An email has been sent with + directions for the pdf download. +
    '; + + /** + * 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 + * @see app.gaslightmedia.com/glmPEAR/HTML/QuickForm/Rules/Zip.php + */ + protected $registeredRules = array(); + + /** + * 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 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 + ) { + // Make sure these end cases are never met. + // These are more for the development phase. + if ($this->email === false && $this->hasContactDB === false) { + PEAR::raiseError( + null, + NO_RECORD, + PEAR_ERROR_CALLBACK, + array(&$this, 'error') + ); + } + if (!is_bool($this->hasContactDB)) { + PEAR::raiseError( + null, + INVALID_DB, + PEAR_ERROR_CALLBACK, + array(&$this, 'error') + ); + } + // we haven't defined the FROM_NEWS_EMAIL constant and + // the email will default to relying on it. + if ( !defined('FROM_NEWS_EMAIL') + && (empty($this->email) && $this->email !== false) + ) { + PEAR::raiseError( + 'You need to define the FROM_NEWS_EMAIL + constant for this form to work correctly', + MISSING_CONSTANT, + PEAR_ERROR_CALLBACK, + array(&$this, 'error') + ); + } + + $this->successMsg = ' +
    + Thank you for requesting the '.SITENAME.' Brochure. You have been sent + an email with a link to download our Brochure, which has been saved as + a PDF. You will need Adobe Acrobat Reader to view this document. If you + do not have Adobe Acrobat Reader, click here to install. +
    '; + parent::__construct( + $formName, + $method, + $action, + $target, + $attributes, + $trackSubmit + ); + + 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 = "Your Pdf request from website " . SITENAME; + } + + /** + * Where are the flexy templates stored at for this class. + */ + define('TEMPLATES_DIR', BASE . 'Toolkit/Contacts/templates'); + + /** + * Where are the compiled flexy templates stored at for this class. + */ + define('COMPILED_DIR', BASE . 'Toolkit/Contacts/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; + + $var = basename(__FILE__, '.php'); + + $callbackUrl = ($_SERVER['HTTPS'] == 'on') ? + BASE_SECURE_URL : BASE_URL; + + $this->configureElements(); + $this->configureRules(); + $this->configureFilters(); + $this->configureDefaults(); + $this->configureConstants(); + } + + // }}} + + // {{{ configureConstats() + + /** + * Constant variables for the form + * + * These values won't get overridden by POST or GET vars + * + * @return void + * @access protected + */ + protected function configureConstants() + { + $constants = array( + 'user_agent' => $_SERVER['HTTP_USER_AGENT'], + 'remote_addr' => $_SERVER['REMOTE_ADDR'], + ); + $this->setupConstants($constants); + } + + // }}} + // {{{ configureDefaults() + + /** + * Initializes default form values + * + * @return void + * @access protected + */ + protected function configureDefaults() + { + if ($contactData = $this->contactExists()) { + $defaults = $contactData; + } else { + $defaults = array( + 'state' => '', + 'mail_ok' => 1, + ); + } + + $this->setupDefaults($defaults); + } + + // }}} + // {{{ configureElements() + + /** + * Form element definitions + * + * @return void + * @access protected + */ + protected function configureElements() + { + // All Elements are created here. This includes group element definitions. + $elements[] = array( + 'type' => 'hidden', + 'req' => false, + 'name' => 'user_agent' + ); + $elements[] = array( + 'type' => 'hidden', + 'req' => false, + 'name' => 'remote_addr' + ); + $elements[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'email', + 'display' => 'Email' + ); + $elements[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'email_rmv', + 'display' => 'Verify Email' + ); + $elements[] = array( + 'type' => 'advcheckbox', + 'req' => false, + 'name' => 'mail_ok', + 'display' => 'Yes, please sign me up for your E-newsletter', + 'opts' => 'Yes', + 'val' => array(0, 1) + ); + + $elements[] = array( + 'type' => 'submit', + 'req' => false, + 'name' => 'submit_rmv', + 'display' => 'Submit Form' + ); + + $this->setupElements($elements); + } + + // }}} + // {{{ configureRules() + + /** + * Form rule definitions + * + * Adds validation rules for the given fields + * + * @return void + * @access protected + */ + protected function configureRules() + { + // Form Rules + $rules[] = array( + 'element' => 'email', + 'message' => 'ERROR: Invalid Email Format!', + 'type' => 'email', + 'format' => null, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + $rules[] = array( + 'element' => array('email', 'email_rmv'), + 'message' => 'ERROR: Your Email Addresses Do Not Match!', + 'type' => 'compare', + 'format' => null, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + $rules[] = array( + 'element' => 'zip', + 'message' => 'ERROR: Invalid Zip!', + 'type' => 'zip', + 'format' => array('requireDBCheck' => false), + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + + $this->setupRules($rules); + } + + // }}} + // {{{ configureFilters() + + /** + * Form filter definitions + * + * Applies a data filter for the given fields when the form is submitted + * + * @return void + * @access protected + */ + protected function configureFilters() + { + $filters[] = array('element' => '__ALL__', 'filter' => 'trim'); + } + + // }}} + // {{{ contactExists() + + /** + * Checks a contact already exists + * + * @return mixed database tuple of query, false on error + * @access protected + */ + protected function contactExists() + { + try { + if (!isset($_GET['id'])) { + return false; + } + $sql = " + SELECT fname, lname, address, address2, city, state, zip, + email, email AS email_rmv, phone, fax, mail_ok + FROM contacts + WHERE id = :cid"; + + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(':cid', $_GET['id'], PDO::PARAM_INT); + $stmt->execute(); + return $stmt->fetch(PDO::FETCH_ASSOC); + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + + // {{{ emailPDFLink() + + /** + * Emails the owner the submitted data from the submitted form + * + * Uses a flexy template to render a nice looking html email. + * Emails the link for pdf to person filling out form. + * + * @return boolean result of the mailing + * @access protected + */ + protected function emailPDFLink() + { + $template = new HTML_Template_Flexy($this->flexyOptions); + $page = new stdClass(); + + $page->email_from = FROM_NEWS_EMAIL; + $page->subject = $this->subject; + $page->client_info = $this->clientInfo; + $page->pdfName = $this->pdfFileName; + $page->pdfLinkURL = BASE_URL.'assets/'.$this->pdfFileName; + $page->pdfFileSize = GLM_TOOLBOX::get_size( + BASE.'assets/' . $this->pdfFileName + ); + + $template->compile('pdfDownloadEmail.html'); + $htmlMsg = $template->bufferedOutputObject($page); + + $crlf = "\n"; + $mimeMail = new Mail_mime($crlf); + $mimeMail->setFrom("{$this->siteName} <{$page->email_from}>"); + $mimeMail->setSubject($this->subject); + $mimeMail->setHTMLBody($htmlMsg); + + $mail =& Mail::factory('mail'); + $body = $mimeMail->get(); + $headers = $mimeMail->headers(); + + $res = $mail->send($this->getSubmitValue('email'), $headers, $body); + if (PEAR::isError($res)) { + return Toolkit_Common::handleError($res); + } else { + return $res; + } + } + + // }}} + // {{{ error() + + /** + * Display errors with the form to the user + * + * @param object $error PEAR Error Object + * + * @return void + * @access public + */ + public function error($error) + { + // make the variables static so that is only has to do the defining + // on the first call. + static $errorMessages; + static $className; + + // define the various error messages + if (!isset($errorMessages)) { + $className = get_class($this); + $errorMessages = array( + FORM_OK => 'No error', + FORM_ERROR => 'Unknown error', + NO_RECORD => 'Setting both properties (email and + hasContactDB) to false in the ' . $className . ' + class will result in no email record being sent and no + record being inserted into the database. There will be + no record that this form was ever filled out.', + INVALID_DB => 'Please set the property hasContactDB + to a boolean value in the class ' . $className . ' + before continuing', + MISSING_CONSTANT => 'You have failed to set a CONSTANT + for the class ' . $className . ' to function properly', + ); + } + + if (!is_null($error->message)) { + $message = $error->message; + } elseif (isset($errorMessages[$error->code])) { + $message = $errorMessages[$error->code]; + } else { + $message = $errorMessages[$error->code]; + $message = $errorMessages[FORM_ERROR]; + } + + echo "
    {$message}
    "; + } + + // }}} + + // {{{ getInterestFields() + + /** + * Returns the field definitions of the contact db interest fields + * + * @return array Group definitions for the interest fields + * @access protected + */ + protected function getInterestFields() + { + if (is_array($this->inquiries)) { + foreach ($this->inquiries as $k => $v) { + $interests[] = array('type' => 'checkbox', + 'req' => false, + 'name' => $k, + 'opts' => $v); + } + } + + return $interests; + } + + // }}} + + // {{{ 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) + { + if (is_array($values['interest']) && !empty($values['interest'])) { + $values['interest'] = ':' . implode( + ':', + array_keys($values['interest']) + ) . ':'; + } + 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; + } 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); + } + return $stmt->execute(); + } 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 + */ + protected function processData($values) + { + // Form data used for the insert/update sql queries and + // the form email. + $e = array( + 'mail_ok', + 'user_agent', + 'remote_addr' + ); + $this->setFormData($e); + + + // If no contact db, return true so we can send owner email. + if (!$this->hasContactDB) { + return true; + } + + // 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]); + } + } + + $this->tableMetaData = Toolkit_Common::getTableMetaData( + $this->dbh, + $this->tableName + ); + // Check if a contact w/ the submitted email already exists. + // if so, then we need to update, if not then do a fresh insert. + try { + $sql = " + SELECT count(*) + FROM {$this->tableName} + WHERE email = :email"; + + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(':email', $values['email'], PDO::PARAM_STR); + $stmt->execute(); + $stmt->bindColumn('count', $contactExists); + $stmt->fetch(); + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + + if ($contactExists) { + return $this->updateData($values); + } else { + return $this->insertData($values); + } + } + + // }}} + + // {{{ setInterestFields() + + /** + * Contact DB interests + * + * @return void + * @access protected + */ + protected function setInterestFields() + { + try { + $sql = " + SELECT * + FROM contact_inq + ORDER BY pos"; + + foreach ($this->dbh->query($sql) as $row) { + $inquiries[$row['id']] = $row['header']; + } + + $this->inquiries = $inquiries; + } catch (PDOException $e) { + Toolkit_Common::handleError($e); + } + } + + // }}} + // {{{ 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} + ', 'comments' + ); + $renderer->setElementTemplate( + ' + '.$required.'{label}'.$error.'{element} + ', 'submit_rmv' + ); + + } + + // }}} + // {{{ toHTML() + + /** + * Handles how to display the current step the user is at in the form + * + * @return string form HTML state + * @access public + */ + public function toHTML() + { + $this->setupRenderers(); + if ($this->validate()) { + $this->cleanForm(); + + if ($this->process(array(&$this, 'processData'), $this->mergeFiles)) { + $this->freeze(); + $ret = $this->emailPDFLink(); + $output = $this->successMsg; + } + $this->sent = true; + } elseif ($this->isSubmitted()) { + $output = $this->errorMsg; + $output .= parent::toHTML(); + } else { + $output = parent::toHTML(); + } + return $output; + } + + // }}} + + // {{{ updateData() + + /** + * Updates the contact in the contact db + * + * @param array $values Form submitted values + * + * @return object Result of the update query + * @access protected + */ + protected function updateData($values) + { + if (is_array($values['interest']) && !empty($values['interest'])) { + $values['interest'] = ':' . implode( + ':', + array_keys($values['interest']) + ) . ':'; + } + 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 email = :email"; + $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); + } + return $stmt->execute(); + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} +} +?> diff --git a/Toolkit/Contacts/SaveTripPlanner.php b/Toolkit/Contacts/SaveTripPlanner.php new file mode 100755 index 0000000..63d7849 --- /dev/null +++ b/Toolkit/Contacts/SaveTripPlanner.php @@ -0,0 +1,658 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @link <> + */ + +/** + * Ask the concierge form + * + * This form handles rendering and processing the contact form. + * + * @category CategoryName + * @package Toolkit_Forms_AskTheConcierge + * @author Jamie Kahgee + * @copyright 2009 Jamie Kahgee + * @license http://www.gaslightmedia.com Gaslightmedia + * @version CVS: $Id: + * @link <> + * @see Toolkit_FormBuilder + */ +class Toolkit_Contacts_SaveTripPlanner extends Toolkit_Contacts_ContactUs +{ + // {{{ properties + + /** + * Contact type to be inserted into the DB as when the form is submitted + * + * This property is only valid when the [hasContactDB] property is set + * to true. + * + * N.B. + * If you subclass this class out to other forms that are + * inserted into the contact db, be sure to make each one of their + * contactType properties unique. We don't check for duplicates. + * + * @var string + * @access public + */ + public $contactType = '4'; + + /** + * 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. + * + * public $email = false; + * + * + * @var unknown + * @access public + */ + public $email = false; + + /** + * Message to display if the form is successfully submitted + * + * @var string + * @access public + */ + public $successMsg = ' +
    + You have successfully created a new account. You may receive a confirmation email. +
    '; + + /** + * 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 public + */ + public $subject; + + protected $plannerListPageId; + protected $plannerFormPageId; + // }}} + // {{{ __construct() + + /** + * Class constructor + * + * @param string $pdo PDO 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( + $pdo, + $formName, + $method, + $action, + $target, + $attributes, + $trackSubmit + ); + $this->subject = 'Travel List from website ' . SITENAME; + $this->plannerListPageId = MEMBER_SESSION_PAGE; + $this->plannerFormPageId = MEMBER_SESSION_FORM; + } + + // }}} + // {{{ configureElements() + + /** + * Form element definitions + * + * @return void + * @access public + */ + public function configureElements() + { + $e = array(); + $this->setInterestFields(); + // Grouped Elements are defined here. + $this->interestsGroups =& $this->getInterestFields(); + + // All Elements are created here. This includes group element definitions. + $e[] = array( + 'type' => 'hidden', + 'req' => false, + 'name' => 'user_agent' + ); + $e[] = array( + 'type' => 'hidden', + 'req' => false, + 'name' => 'remote_addr' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'fname', + 'display' => 'First Name' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'lname', + 'display' => 'Last Name' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'address', + 'display' => 'Address 1' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'address2', + 'display' => 'Address 2' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'city', + 'display' => 'City' + ); + $e[] = array( + 'type' => 'select', + 'req' => false, + 'name' => 'state', + 'display' => 'State/Province', + 'opts' => $GLOBALS['states'] + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'zip', + 'display' => 'ZIP/Postal Code' + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'email', + 'display' => 'Email' + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'email_rmv', + 'display' => 'Verify Email' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'phone', + 'display' => 'Phone' + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'password', + 'display' => 'Password' + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'verify_password', + 'display' => 'Verify Password' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'fax', + 'display' => 'Fax' + ); + $e[] = array( + 'type' => 'advcheckbox', + 'req' => false, + 'name' => 'mail_ok', + 'display' => 'Yes, I would like to receive Email Newsletters', + 'opts' => 'Yes', + 'val' => array(0, 1) + ); + if (is_array($this->interestsGroups)) { + foreach ($this->interestsGroups as $group => $gData) { + $this->myGroups[] = $gData; + $e[] = array( + 'type' => 'group', + 'req' => false, + 'name' => 'interest['.$group.']', + 'group' => $gData, + 'label' => $group, + 'seperator' => ' ', + 'appendName' => true + ); + } + } + $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 Form' + ); + + $this->setupElements($e); + } + + // }}} + // {{{ configureRules() + + /** + * Form rule definitions + * + * Adds validation rules for the given fields + * + * @return void + * @access public + */ + public function configureRules() + { + $r = array(); + // Form Rules + $r[] = array( + 'element' => array('email', 'email_rmv'), + 'message' => 'ERROR: Your Email Addresses Do Not Match!', + 'type' => 'compare', + 'format' => null, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + $r[] = array( + 'element' => array('password', 'verify_password'), + 'message' => 'ERROR: Your Passwords do not match!', + 'type' => 'compare', + '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' => 'state', + 'message' => 'ERROR: Invalid State!', + 'type' => 'numeric', + 'format' => null, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + */ + $r[] = array( + 'element' => 'phone', + 'message' => 'ERROR: Invalid number (xxx) xxx-xxxx!', + 'type' => 'phone', + 'format' => null, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + $r[] = array( + 'element' => 'fax', + 'message' => 'ERROR: Invalid number (xxx) xxx-xxxx!', + 'type' => 'phone', + 'format' => null, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + $r[] = array( + 'element' => 'zip', + 'message' => 'ERROR: Invalid Zip!', + 'type' => 'zip', + 'format' => array('requireDBCheck' => false), + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + $r[] = array( + 'element' => 'mail_ok', + 'message' => 'ERROR: Invalid Value!', + 'type' => 'numeric', + 'format' => null, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + $r[] = array( + 'element' => 'captcha_rmv', + 'message' => 'ERROR: Incorrect verification code!', + 'type' => 'CAPTCHA', + 'format' => $this->captchaQuestion, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + + $this->setupRules($r); + } + + // }}} + // {{{ contactExists() + + /** + * Checks for a duplicate email address already in the DB. + * + * @param string $email The email address to check for in the DB + * + * @return boolean If the email address already exists + * @access protected + */ + protected function contactExists($email) + { + // Check if a contact w/ the submitted email already exists. + // if so, then we need to update, if not then do a fresh insert. + try { + $sql = " + SELECT id,password + FROM contact + WHERE email = :email"; + + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(':email', $email, PDO::PARAM_STR); + $stmt->execute(); + //$stmt->bindColumn('id', $contactExists); + //$stmt->bindColumn('password', $password); + $row = $stmt->fetch(); + //die('
    '.print_r($row, true).'
    '); + if (!empty($row)) { + return array( + 'contactId' => $row['id'], + 'password' => $row['password'] + ); + } else { + return false; + } + + } 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) + { + unset($values['comments']); + $values['contact_type'] = ":{$this->contactType}:"; + if (is_array($values['interest']) && !empty($values['interest'])) { + $values['interest'] = ':' . implode(':', array_keys($values['interest'])) . ':'; + } + try { + $sql = Toolkit_Common::createSQLInsert( + $this->tableName, + array_keys($values) + ); + + $sql .= " RETURNING id"; + return Toolkit_Common::processQuery( + $this->dbh, + $this->tableName, + $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( + 'user_agent', + 'remote_addr', + 'contact_type', + 'catid', + 'cPage', + ); + $this->setFormData($e); + + + // If no contact db, return true so we can send owner email. + if (!$this->hasContactDB) { + return true; + } + + // Get rid of any elements in the values array that + // aren't going to be used when inserting/updating the db. + $values = Toolkit_Common::cleanArray($values); + + // Send data off to StreamSend + if ( defined('STREAMSEND_FORMS_API') + && STREAMSEND_FORMS_API + && $values['mail_ok'] + ) { + // Insert the record into the streamsend server + $streamSend = new Toolkit_Contacts_StreamSend(); + $streamSend->addContact($values); + } + + // Check if we are updating an existing contact or not + // question: is this the best approach? what if someone else + // sends a form through w/ different data but the same emil addy + // the old users data can be completely wiped out. + $existingContact = $this->contactExists($values['email']); + + $values['password'] = md5($values['password']); + unset($values['catid']); + unset($values['cPage']); + $tripPlannerAuth =& new Toolkit_Members_TripPlanner_TripAuth('DB', array(), '', false); + $tripPlannerAuth->setIdle(); + $tripPlannerAuth->start(); + $sessionList = new Toolkit_Members_TripPlanner_Sessions( + Toolkit_Database::getInstance(), + &$tripPlannerAuth + ); + if (is_array($existingContact)) { + // if there already in the database then give a message that they're already in and need to login + // this is true only if they already have a password set + if (!$existingContact['password']) { + $this->updateData($values); + $contactId = $existingContact['contactId']; + $tripPlannerAuth->setAuth($values['email']); + $tripPlannerAuth->setAuthData('id', $contactId); + $tripPlannerAuth->setAuthData('username', $values['email']); + $sessionList->saveList($contactId); + return true; + } else { + $toolbox = new GLM_TEMPLATE(HOME_ID); + $this->errorMsg = '

    Your Email address already exist. Please sign-in.

    '; + return false; + } + } else { + $contactId = $this->insertData($values); + $contactData = $this->contactExists($values['email']); + $contactId = $contactData['contactId']; + $tripPlannerAuth->setAuth($values['email']); + $tripPlannerAuth->setAuthData('id', $contactId); + $tripPlannerAuth->setAuthData('username', $values['email']); + $sessionList->saveList($contactId); + return true; + } + } + + // }}} + // {{{ toHTML() + + /** + * Handles how to display the current step the user is at in the form + * + * destroying and resetting the captcha value dis-allows someone from + * re-sending a form on a previous captcha. + * + * @return string form HTML state + * @access public + */ + public function toHTML() + { + $this->setupRenderers(); + if ($this->validate()) { + $this->captchaQuestion->destroy(); + $this->cleanForm(); + + if ($this->process(array(&$this, 'processData'), $this->mergeFiles)) { + $this->freeze(); + $output = $this->successMsg; + } else { + $output = $this->errorMsg; + //$output .= parent::toHTML(); + } + $this->sent = true; + } elseif ($this->isSubmitted()) { + $this->captchaQuestion->destroy(); + $this->captchaAnswer->setValue(''); + //$output = $this->errorMsg; + $output .= parent::toHTML(); + } else { + $this->captchaQuestion->destroy(); + $this->captchaAnswer->setValue(''); + $output .= parent::toHTML(); + } + return $output; + } + + // }}} + // {{{ updateData() + + /** + * Updates the contact in the contact db + * + * @param array $values Form submitted values + * + * @return object Result of the update query + * @access protected + */ + protected function updateData($values) + { + unset($values['comments']); + if (is_array($values['interest']) && !empty($values['interest'])) { + $values['interest'] = ':' . implode(':', array_keys($values['interest'])) . ':'; + } + + try { + // Get all the existing contact type data + $sql = " + SELECT contact_type + FROM {$this->tableName} + WHERE email = :email"; + + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(':email', $values['email'], PDO::PARAM_STR); + $stmt->execute(); + $stmt->bindColumn('contact_type', $cType); + $stmt->fetch(); + + $existingTypes = explode(':', $cType); + if (!in_array($this->contactType, $existingTypes)) { + $values['contact_type'] = "$cType{$this->contactType}:"; + } + + $sql = Toolkit_Common::createSQLUpdate( + $this->tableName, + array_keys($values), + array('email = :email') + ); + + + return Toolkit_Common::processQuery( + $this->dbh, + $this->tableName, + $sql, + $values + ); + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} +} +?> diff --git a/Toolkit/Contacts/SendTripPlanner.php b/Toolkit/Contacts/SendTripPlanner.php new file mode 100755 index 0000000..737df6c --- /dev/null +++ b/Toolkit/Contacts/SendTripPlanner.php @@ -0,0 +1,748 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @link <> + */ + +/** + * Ask the concierge form + * + * This form handles rendering and processing the contact form. + * + * @category CategoryName + * @package Toolkit_Forms_AskTheConcierge + * @author Jamie Kahgee + * @copyright 2009 Jamie Kahgee + * @license http://www.gaslightmedia.com Gaslightmedia + * @version CVS: $Id: + * @link <> + * @see Toolkit_FormBuilder + */ +class Toolkit_Contacts_SendTripPlanner extends Toolkit_Contacts_ContactUs +{ + // {{{ properties + + /** + * Contact type to be inserted into the DB as when the form is submitted + * + * This property is only valid when the [hasContactDB] property is set + * to true. + * + * N.B. + * If you subclass this class out to other forms that are + * inserted into the contact db, be sure to make each one of their + * contactType properties unique. We don't check for duplicates. + * + * @var string + * @access public + */ + public $contactType = '4'; + + /** + * 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. + * + * public $email = false; + * + * + * @var unknown + * @access public + */ + public $email = false; + + /** + * Message to display if the form is successfully submitted + * + * @var string + * @access public + */ + public $successMsg = ' +
    +

    Thank you for adding these businesses to your Trip Planner. Your +information is currently being sent to each business so they may contact you regarding your +visit to The Upper Peninsula of Michigan.

    +
    '; + + /** + * 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 public + */ + public $subject; + + // }}} + // {{{ __construct() + + /** + * Class constructor + * + * @param string $pdo Passed in PDO 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( + $pdo, + $formName, + $method, + $action, + $target, + $attributes, + $trackSubmit + ); + $this->subject = 'Travel List from website ' . SITENAME; + } + + // }}} + // {{{ configureDefaults() + + /** + * Initializes default form values + * + * @return void + * @access public + */ + public function configureDefaults() + { + $defaults = array( + 'state' => '', + 'mail_ok' => 1, + 'catid' => $_REQUEST['catid'], + 'cPage' => $_REQUEST['cPage'] + ); + + $this->setupDefaults($defaults); + } + + // }}} + // {{{ configureElements() + + /** + * Form element definitions + * + * @return void + * @access public + */ + public function configureElements() + { + $e = array(); + $this->setInterestFields(); + // Grouped Elements are defined here. + $this->interestsGroups =& $this->getInterestFields(); + + // All Elements are created here. This includes group element definitions. + $e[] = array( + 'type' => 'hidden', + 'req' => false, + 'name' => 'catid' + ); + $e[] = array( + 'type' => 'hidden', + 'req' => false, + 'name' => 'cPage' + ); + $e[] = array( + 'type' => 'hidden', + 'req' => false, + 'name' => 'user_agent' + ); + $e[] = array( + 'type' => 'hidden', + 'req' => false, + 'name' => 'remote_addr' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'fname', + 'display' => 'First Name' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'lname', + 'display' => 'Last Name' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'address', + 'display' => 'Address 1' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'address2', + 'display' => 'Address 2' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'city', + 'display' => 'City' + ); + $e[] = array( + 'type' => 'select', + 'req' => false, + 'name' => 'state', + 'display' => 'State/Province', + 'opts' => $GLOBALS['states'] + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'zip', + 'display' => 'ZIP/Postal Code' + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'email', + 'display' => 'Email' + ); + $e[] = array( + 'type' => 'text', + 'req' => true, + 'name' => 'email_rmv', + 'display' => 'Verify Email' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'phone', + 'display' => 'Phone' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'fax', + 'display' => 'Fax' + ); + $e[] = array( + 'type' => 'textarea', + 'req' => false, + 'name' => 'comments', + 'display' => 'Comments' + ); + $e[] = array( + 'type' => 'advcheckbox', + 'req' => false, + 'name' => 'mail_ok', + 'display' => 'Yes, I would like to receive Email Newsletters', + 'opts' => 'Yes', + 'val' => array(0, 1) + ); + if (is_array($this->interestsGroups)) { + foreach ($this->interestsGroups as $group => $gData) { + $this->myGroups[] = $gData; + $e[] = array( + 'type' => 'group', + 'req' => false, + 'name' => 'interest['.$group.']', + 'group' => $gData, + 'label' => $group, + 'seperator' => ' ', + 'appendName' => true + ); + } + } + $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 Form' + ); + + $this->setupElements($e); + } + + // }}} + // {{{ configureRules() + + /** + * Form rule definitions + * + * Adds validation rules for the given fields + * + * @return void + * @access public + */ + public function configureRules() + { + $r = array(); + // Form Rules + $r[] = array( + 'element' => array('email', 'email_rmv'), + 'message' => 'ERROR: Your Email Addresses Do Not Match!', + 'type' => 'compare', + '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' => 'state', + 'message' => 'ERROR: Invalid State!', + 'type' => 'numeric', + 'format' => null, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + */ + $r[] = array( + 'element' => 'phone', + 'message' => 'ERROR: Invalid number (xxx) xxx-xxxx!', + 'type' => 'phone', + 'format' => null, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + $r[] = array( + 'element' => 'fax', + 'message' => 'ERROR: Invalid number (xxx) xxx-xxxx!', + 'type' => 'phone', + 'format' => null, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + $r[] = array( + 'element' => 'zip', + 'message' => 'ERROR: Invalid Zip!', + 'type' => 'zip', + 'format' => array('requireDBCheck' => false), + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + $r[] = array( + 'element' => 'mail_ok', + 'message' => 'ERROR: Invalid Value!', + 'type' => 'numeric', + 'format' => null, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + $r[] = array( + 'element' => 'captcha_rmv', + 'message' => 'ERROR: Incorrect verification code!', + 'type' => 'CAPTCHA', + 'format' => $this->captchaQuestion, + 'validation' => $this->validationType, + 'reset' => true, + 'force' => false + ); + + $this->setupRules($r); + } + + // }}} + + // {{{ 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. + unset($values['catid']); + unset($values['cPage']); + $e = array( + 'user_agent', + 'remote_addr', + 'contact_type', + ); + $this->setFormData($e); + + + // If no contact db, return true so we can send owner email. + if (!$this->hasContactDB) { + return true; + } + + // Get rid of any elements in the values array that + // aren't going to be used when inserting/updating the db. + $values = Toolkit_Common::cleanArray($values); + + // Send data off to StreamSend + if ( defined('STREAMSEND_FORMS_API') + && STREAMSEND_FORMS_API + && $values['mail_ok'] + ) { + // Insert the record into the streamsend server + $streamSend = new Toolkit_Contacts_StreamSend(); + $streamSend->addContact($values); + } + + // Check if we are updating an existing contact or not + // question: is this the best approach? what if someone else + // sends a form through w/ different data but the same emil addy + // the old users data can be completely wiped out. + $existingContact = $this->contactExists($values['email']); + + if ($existingContact) { + return $this->updateData($values); + } else { + return $this->insertData($values); + } + } + + // }}} + + // {{{ sendEmails() + + /** + * sendEmails + * + * From the list of emails contained in $_SESSIEN['wish_list'] + * send out emails to each email address + * only if we're on the production server + * if on the development server send to OWNER_EMAIL + * + * @return void + * @access public + */ + function sendEmails() + { + $hasInterestField = $this->elementExists('interest'); + + $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')); + + $page->email_from = OWNER_EMAIL; + $page->subject = $this->subject; + $page->client_info = $this->clientInfo; + $page->fname = $this->getSubmitValue('fname'); + $page->lname = $this->getSubmitValue('lname'); + $page->formData = $this->formData; + + // unset some extra fields + unset( + $page->formData['catid'], + $page->formData['cPage'] + ); + + if ($hasInterestField) { + // Clean up the interests so they will look nice in the email + $page->formData['interest']['nowrap'] = 'nowrap'; + $page->formData['interest']['element'] = null; + $g =& $this->getElement('interest'); + $ge =& $g->getElements(); + $interests = array(); + foreach ($ge as $e) { + if ($e->getChecked()) { + $interests[] = $e->getText(); + } + } + $page->formData['interest']['element'] = implode('
    ', $interests); + } + + if ($this->elementExists('mail_ok')) { + // Clean up the mail_ok flag so its human readable + $page->formData['mail_ok']['element'] + = ($page->formData['mail_ok']['element']) ? 'Yes' : 'No'; + } + + $template->compile('emailOwner.tpl'); + $htmlMsg = $template->bufferedOutputObject($page); + + if ($hasInterestField) { + // Text version can't have HTML in it + // so reset the interests to use commas + $page->formData['interest']['element'] = implode(", ", $interests); + } + $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("Online Form <{$page->email_from}>"); + $mimeMail->setSubject($this->subject); + $mimeMail->setHTMLBody($htmlMsg); + $mimeMail->setTXTBody($msg); + + $mail =& Mail::factory('mail'); + $body = $mimeMail->get(); + $setHeader['Reply-To'] = "{$this->getSubmitValue('fname')} {$this->getSubmitValue('lname')} <{$this->getSubmitValue('email')}>"; + $headers = $mimeMail->headers($setHeader); + $sql = " + SELECT member_contact_email + FROM member + WHERE member_id = :member_id"; + $getMemberEmail = $this->dbh->prepare($sql); + + switch (GLM_HOST_ID) { + case "DEVELOPMENT": + // code for sending email + if (is_array($_SESSION['wish_list']) && !empty($_SESSION['wish_list'])) { + foreach ($_SESSION['wish_list'] as $member_id => $row) { + try { + $getMemberEmail->bindParam(":member_id", $member_id, PDO::PARAM_INT); + $getMemberEmail->execute(); + $memberEmail = $getMemberEmail->fetchColumn(); + } catch(PDOException $e) { + return Toolkit_Common::handleError($e); + } + if (GLM_TOOLBOX::valid_email($memberEmail)) { + echo '

    Send mail to: '.$memberEmail.'

    '; + } + } + } + $res = $mail->send(OWNER_EMAIL, $headers, $body); + if (PEAR::isError($res)) { + return Toolkit_Common::handleError($res); + } + break; + case "PRODUCTION": + if (is_array($_SESSION['wish_list']) && !empty($_SESSION['wish_list'])) { + foreach ($_SESSION['wish_list'] as $member_id => $row) { + try { + $getMemberEmail->bindParam(":member_id", $member_id, PDO::PARAM_INT); + $getMemberEmail->execute(); + $memberEmail = $getMemberEmail->fetchColumn(); + } catch(PDOException $e) { + return Toolkit_Common::handleError($e); + } + // code for sending emails + if (GLM_TOOLBOX::valid_email($memberEmail)) { + $res = $mail->send($memberEmail, $headers, $body); + if (PEAR::isError($res)) { + return Toolkit_Common::handleError($res); + } + } + } + } + break; + } + $tripPlannerAuth =& new Toolkit_Members_TripPlanner_TripAuth('DB', array(), '', false); + $tripPlannerAuth->setIdle(); + $tripPlannerAuth->start(); + $sessionList = new Toolkit_Members_TripPlanner_Sessions($this->dbh, &$tripPlannerAuth); + $sessionList->dumpList(); + return $res; + } + + // }}} + // {{{ showDirectList() + + /** + * showDirectList + * + * Display the list of members in $_SESSION['wish_list'] + * + * @return void + * @access public + */ + function showDirectList() + { + // Initiate HTML_Template_Flexy. + $template = new HTML_Template_Flexy($this->flexyOptions); + $page = new stdClass(); + $page->memberDirect = $page->memberDirectNoEmail = array(); + if (is_array($_SESSION['wish_list']) && !empty($_SESSION['wish_list'])) { + $sql = " + SELECT member_name,member_contact_email,phone,toll_free + FROM member + WHERE member_id = :member_id"; + $getMemberData = $this->dbh->prepare($sql); + $mACount = $mBCount = 0; + foreach ($_SESSION['wish_list'] as $member_id => $row) { + try { + $getMemberData->bindParam(":member_id", $member_id, PDO::PARAM_INT); + $getMemberData->execute(); + $memberData = $getMemberData->fetch(); + $memberName = $memberData['member_name']; + $memberPhone = $memberData['phone']; + $memberTollFree = $memberData['toll_free']; + } catch(PDOException $e) { + Toolkit_Common::handleError($e); + } + if ($memberData['member_contact_email']) { + $page->memberDirect[] = array( + 'memberName' => $memberName, + 'memberPhone' => $memberPhone, + 'memberTollFree' => $memberTollFree, + 'memberLink' => BASE_URL + .'index.php?catid='.$row['catid'].'&member_id='.$member_id, + 'deleteLink' => BASE_URL + .'Toolkit/Members/TripPlanner/' + .'wish-list.php?catid=' + .$_REQUEST['catid'].'&member_id=' . $member_id + . '&cPage=' . urlencode($_REQUEST['cPage']), + 'trclass' => (($mACount % 2 == 0) ? 'tr1': 'tr2') + ); + $mACount++; + } else { + $page->memberDirectNoEmail[] = array( + 'memberName' => $memberName, + 'memberPhone' => $memberPhone, + 'memberTollFree' => $memberTollFree, + 'memberLink' => BASE_URL + .'index.php?catid='.$row['catid'].'&member_id='.$member_id, + 'deleteLink' => BASE_URL + .'Toolkit/Members/TripPlanner/' + . 'wish-list.php?catid=' + . $_REQUEST['catid'].'&member_id=' . $member_id + . '&cPage=' . urlencode($_REQUEST['cPage']), + 'trclass' => (($mBCount % 2 == 0) ? 'tr1': 'tr2') + ); + $mBCount++; + } + } + } + $this->totalMembersEmails = $mACount; + $this->totalMembersNoEmails = $mBCount; + // Compile the direct-list.html from the templates directory. + $template->compile('direct-list.html'); + + // Merge compiled template with the $page object. + $out = $template->bufferedOutputObject($page); + return $out; + } + // }}} + // {{{ showNoList() + + /** + * showNoList + * + * What to display If nothing is in $_SESSION['wish_list'] + * + * @return void + * @access public + */ + function showNoList() + { + // Initiate HTML_Template_Flexy. + $template = new HTML_Template_Flexy($this->flexyOptions); + $page = new stdClass(); + $page->baseUrl = BASE_URL; + // Compile the direct-nolist.html from the templates directory. + $template->compile('direct-nolist.html'); + + // Merge compiled template with the $page object. + $out = $template->bufferedOutputObject($page); + return $out; + } + // }}} + // {{{ toHTML() + + /** + * Handles how to display the current step the user is at in the form + * + * destroying and resetting the captcha value dis-allows someone from + * re-sending a form on a previous captcha. + * + * @return string form HTML state + * @access public + */ + public function toHTML() + { + $this->setupRenderers(); + if ($this->validate()) { + $this->captchaQuestion->destroy(); + $this->cleanForm(); + + if ($this->process(array(&$this, 'processData'), $this->mergeFiles)) { + $this->freeze(); + $this->sendEmails(); + $output = $this->successMsg; + } + $this->sent = true; + } elseif ($this->isSubmitted()) { + $this->captchaQuestion->destroy(); + $this->captchaAnswer->setValue(''); + $output .= parent::toHTML(); + } else { + $this->captchaQuestion->destroy(); + $this->captchaAnswer->setValue(''); + $output = $this->showDirectList(); + if ($this->totalMembersEmails > 0) { + $output .= parent::toHTML(); + } + } + return $output; + } + + // }}} +} +?> diff --git a/Toolkit/Contacts/StreamSend.php b/Toolkit/Contacts/StreamSend.php new file mode 100755 index 0000000..dd7658c --- /dev/null +++ b/Toolkit/Contacts/StreamSend.php @@ -0,0 +1,201 @@ + + * @copyright 2009 Gaslight Media + * @license Gaslight Media + * @version CVS: $Id: StreamSend.php,v 1.4 2009/09/16 11:31:23 jamie Exp $ + * @link <> + */ + +/** + * Default parameters for contact create operations. + * Note that these are strings for use in XML data not true/false values. + * If false, the person will be created with a status of pending + */ +define('STREAMSEND_DEFAULT_ACTIVATE', 'false'); +/** + * If activate is false, setting this to true will trigger the sending of the built-in + * activation notification; if activate is true, this setting has no effect + */ +define('STREAMSEND_DEFAULT_DELIVER_ACTIVATION', 'true'); +/** + * If activate is true, setting this to true will trigger the sending of the built-in + * welcome notification; if activate is false, this setting has no effect + */ +define('STREAMSEND_DEFAULT_DELIVER_WELCOME', 'false'); +/** + * URI for streamsend API + */ +define('STREAMSEND_BASE_URL', "https://app.streamsend.com"); + +/** + * Toolkit_Contacts_StreamSend + * + * Contact support class for inergration with StreamSend API + * + * @category Contacts + * @package Toolkit_Contacts + * @author Steve Sutton + * @copyright 2009 Gaslight Media + * @license Gaslight Media + * @link <> + */ +class Toolkit_Contacts_StreamSend +{ + // {{{ Class Properties + + + /** + * Description for public + * @var boolean + * @access public + */ + public $debug = false; + + /** + * streamSendFields + * + * array with key values matching the gaslight contact tabel to the + * StreamSend field (normal fields) + * + * @var array + * @access protected + */ + protected $streamSendFields = array( + 'email' => 'email-address', + 'fname' => 'first-name', + 'lname' => 'last-name', + 'address' => 'address1', + 'address2' => 'address2', + 'city' => 'city', + 'state' => 'stateprovince', + 'zip' => 'postal-code', + 'phone' => 'phone-number' + ); + + /** + * contactInqTypes + * + * array with key values matching the gaslight contact_inq tabel to the + * StreamSend field (Radio fields) + * key = id from contact_inq table + * value = name from contact_inq_table + * value is same name as the StreamSend fieldname + * + * @var array + * @access protected + */ + protected $contactInqTypes = array(); + + /** + * booleanTypes + * + * StreamSend fields (boolean fields) an array of field names for the + * boolean field types + * + * @var array + * @access protected + */ + protected $booleanTypes = array(); + // }}} + // {{{ __construct() + + + /** + * __construct( + * + * @return void + * @access public + */ + public function __construct() + { + } + + + // }}} + // {{{ addContact() + + + /** + * addContact + * + * Given $values from a Toolkit_Contacts Form add Contact + * + * @param array $values Parameter description (if any) ... + * + * @return boolean Return true if successfull + * @access public + */ + public function addContact($values) + { + // check the array $values to make sure it is correct + if (is_array($values) && !empty($values)) { + include_once GLM_APP_BASE.'StreamSend/class_streamsend_api.inc'; + // initialize the streamsend object + $ss = new streamSend (STREAMSEND_BASE_URL, STREAMSEND_LOGIN_ID, + STREAMSEND_KEY); + $ss->debug = $this->debug; + $contactData = array(); + $values[$type] = 1; + foreach ($this->streamSendFields as $glmName => $ssName) { + switch ($glmName) { + case "state": + $contactData[$ssName] = ($values[$glmName]) ? $GLOBALS['states'][$values[$glmName]]: ''; + break; + default: + $contactData[$ssName] = $values[$glmName]; + break; + } + } + foreach ($this->contactInqTypes as $contactInqId => $name) { + $slug = str_replace(" ", "-", strtolower($this->contactInqTypes[$contactInqId])); + if ($values['interest'][$contactInqId]) { + $contactData[$slug] = 'Yes'; + } else { + $contactData[$slug] = 'No'; + } + } + foreach ($this->booleanTypes as $name) { + if ($values[$name]) { + $contactData[$name] = 'Yes'; + } else { + $contactData[$name] = 'No'; + } + } + $contacts = $ss->contactCreate( + $contactData, + STREAMSEND_DEFAULT_ACTIVATE, + STREAMSEND_DEFAULT_DELIVER_ACTIVATION, + STREAMSEND_DEFAULT_DELIVER_WELCOME + ); + if (!$contacts) { + + // show errors if on development server + switch (GLM_HOST_ID) { + case "DEVELOPMENT": + echo "

    A total and complete failure occured."; + break; + case "PRODUCTION": + break; + } + } + if ($ss->debug == true) { + echo '

    Debug Results

    '.$ss->debugBuffer.'

    '; + } + return true; + } + return false; + } + + + // }}} +} +?> diff --git a/Toolkit/Contacts/TellAFriend.php b/Toolkit/Contacts/TellAFriend.php new file mode 100755 index 0000000..046f93d --- /dev/null +++ b/Toolkit/Contacts/TellAFriend.php @@ -0,0 +1,610 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @version CVS: $Id: TellAFriend.php,v 1.8 2010/01/28 16:33:53 jamie Exp $ + * @link http://demo.gaslightmedia.com + */ + +/** + * Error codes for Toolkit_Contacts_ContactUs + * + * Codes are mapped to textual messaged by errorMessage() method, + * if you add a new code be sure to add a new message for it to errorMessage() + * + * @see Toolkit_Contacts_TellAFriend::errorMessage() + */ +define('FORM_OK', 1); +define('FORM_ERROR', -1); +define('NO_RECORD', -2); +define('INVALID_DB', -3); +define('MISSING_CONSTANT', -4); + +/** + * GLM Tell a Friend form + * + * This form handles rendering and processing the contact us form. + * Controls the email functionality of the form, whether the client + * has a contact DB to store contact records and how to insert/update + * submitted form values. + * + * @category Contacts + * @package Toolkit_Contacts + * @author Jamie Kahgee + * @copyright 2009 Jamie Kahgee + * @license http://www.gaslightmedia.com Gaslightmedia + * @link <> + * @see Toolkit_FormBuilder + */ +class Toolkit_Contacts_TellAFriend extends Toolkit_FormBuilder +{ + // {{{ properties + + /** + * Table in Database which holds the contact data + * + * @var string + * @access public + */ + public $tableName = 'contact'; + + /** + * 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; + + /** + * Used in the email template for the client info string at the bottom + * + * @var string + * @access protected + */ + protected $clientInfo = array( + 'name' => 'Gaslight Media', + 'address' => '120 E. Lake St.', + 'city' => 'Petoskey', + 'state' => 'MI', + 'zip' => '49770', + 'phone' => '231.487.0697', + ); + + /** + * 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 = 'Demo Gaslight Media'; + + /** + * 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 = 'Tell a Friend'; + + /** + * Whether the site has a contact DB to store contact records + * + * If this value is set to false, an email will still be sent to the + * addressed specified in the email property. + * + * @var boolean + * @access protected + */ + protected $hasContactDB = false; + + /** + * The interests from the contact db + * + * @var array + * @access protected + */ + protected $inquiries = array(); + + /** + * Message to display if the form is successfully submitted + * + * @var string + * @access protected + */ + protected $successMsg = ' +
    + Thank You, your message is sent. +
    '; + + /** + * 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 + * @see app.gaslightmedia.com/glmPEAR/HTML/QuickForm/Rules/Zip.php + */ + protected $registeredRules = array(); + + /** + * 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 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 + ) { + // Make sure these end cases are never met. + // These are more for the development phase. + if ($this->email === false && $this->hasContactDB === false) { + PEAR::raiseError( + null, + NO_RECORD, + PEAR_ERROR_CALLBACK, + array(&$this, 'error') + ); + } + if (!is_bool($this->hasContactDB)) { + PEAR::raiseError( + null, + INVALID_DB, + PEAR_ERROR_CALLBACK, + array(&$this, 'error') + ); + } + // we haven't defined the FROM_NEWS_EMAIL constant and + // the email will default to relying on it. + if ( !defined('FROM_NEWS_EMAIL') + && (empty($this->email) && $this->email !== false) + ) { + PEAR::raiseError( + 'You need to define the FROM_NEWS_EMAIL + constant for this form to work correctly', + MISSING_CONSTANT, + PEAR_ERROR_CALLBACK, + array(&$this, 'error') + ); + } + + parent::__construct( + $formName, + $method, + $action, + $target, + $attributes, + $trackSubmit + ); + + 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 = "Your Pdf request from website " . SITENAME; + } + + /** + * Where are the flexy templates stored at for this class. + */ + define('TEMPLATES_DIR', BASE . 'Toolkit/Contacts/templates'); + + /** + * Where are the compiled flexy templates stored at for this class. + */ + define('COMPILED_DIR', BASE . 'Toolkit/Contacts/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->flexyOptions['charset'] = 'utf-8'; + $this->flexyOptions['nonHTML'] = true; + + $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, + ), + ); + + $this->configureElements(); + $this->configureRules(); + $this->configureFilters(); + $this->configureDefaults(); + $this->configureConstants(); + } + + // }}} + // {{{ configureConstats() + + /** + * Constant variables for the form + * + * These values won't get overridden by POST or GET vars + * + * @return void + * @access protected + */ + protected function configureConstants() + { + $constants = array( + 'user_agent' => $_SERVER['HTTP_USER_AGENT'], + 'remote_addr' => $_SERVER['REMOTE_ADDR'], + ); + $this->setupConstants($constants); + } + + // }}} + // {{{ configureDefaults() + + /** + * Initializes default form values + * + * @return void + * @access protected + */ + protected function configureDefaults() + { + $defaults = array( + ); + + $this->setupDefaults($defaults); + } + + // }}} + // {{{ configureElements() + + /** + * Form element definitions + * + * @return void + * @access protected + */ + protected function configureElements() + { + // All Elements are created here. This includes group element definitions. + $elements[] = array('type' => 'hidden', 'req' => false, 'name' => 'user_agent'); + $elements[] = array('type' => 'hidden', 'req' => false, 'name' => 'remote_addr'); + $elements[] = array('type' => 'text', 'req' => true, 'name' => 'fname', 'display' => 'Friends Name:'); + $elements[] = array('type' => 'text', 'req' => true, 'name' => 'femail', 'display' => 'Friends Email:'); + + $elements[] = array('type' => 'text', 'req' => true, 'name' => 'yname', 'display' => 'Your Name:'); + $elements[] = array('type' => 'text', 'req' => true, 'name' => 'yemail', 'display' => 'Your Email:'); + + $elements[] = array('type' => 'CAPTCHA_Image', 'req' => false, 'name' => 'captcha_question', 'display' => null, 'opts' => $this->captchaOptions); + $elements[] = array('type' => 'text', 'req' => true, 'name' => 'captcha_rmv', 'display' => 'Enter the letters you see'); + $elements[] = array('type' => 'submit', 'req' => false, 'name' => 'submit_rmv', 'display' => 'Send Email'); + + $this->setupElements($elements); + } + + // }}} + // {{{ configureRules() + + /** + * Form rule definitions + * + * Adds validation rules for the given fields + * + * @return void + * @access protected + */ + protected function configureRules() + { + // Form Rules + $rules[] = array('element' => 'email', 'message' => 'ERROR: Invalid Email Format!', 'type' => 'email', 'format' => null, 'validation' => $this->validationType, 'reset' => true, 'force' => false); + + $rules[] = 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($rules); + } + + // }}} + // {{{ configureFilters() + + /** + * Form filter definitions + * + * Applies a data filter for the given fields when the form is submitted + * + * @return void + * @access protected + */ + protected function configureFilters() + { + $filters[] = array('element' => '__ALL__', 'filter' => 'trim'); + } + + // }}} + // {{{ emailFriend() + + /** + * Emails the owner the submitted data from the submitted form + * + * Uses a flexy template to render a nice looking html email. + * Emails the link for pdf to person filling out form. + * + * @return boolean result of the mailing + * @access protected + */ + protected function emailFriend() + { + $template = new HTML_Template_Flexy($this->flexyOptions); + $page = new stdClass(); + + $page->email_from = FROM_NEWS_EMAIL; + $page->fname = $this->getSubmitValue('fname'); + $page->yname = $this->getSubmitValue('yname'); + $page->subject = $this->subject; + + $template->compile('friendEmail.html'); + $htmlMsg = $template->bufferedOutputObject($page); + + $crlf = "\n"; + $mimeMail = new Mail_mime($crlf); + $mimeMail->setFrom("{$this->siteName} <{$page->email_from}>"); + $mimeMail->setSubject($this->subject); + $mimeMail->setHTMLBody($htmlMsg); + + $mail =& Mail::factory('mail'); + $setting = array( + 'text_charset'=>'utf-8', + 'html_charset'=>'utf-8', + ); + $body = $mimeMail->get($setting); + $headers = $mimeMail->headers(array('Reply-To'=>$this->getSubmitValue('femail')), true); + + $res = $mail->send($this->getSubmitValue('femail'), $headers, $body); + if (PEAR::isError($res)) { + return Toolkit_Common::handleError($res); + } else { + return $res; + } + } + + // }}} + // {{{ error() + + /** + * Display errors with the form to the user + * + * @param object $error PEAR Error Object + * + * @return void + * @access public + */ + public function error($error) + { + // make the variables static so that is only has to do the defining + // on the first call. + static $errorMessages; + static $className; + + // define the various error messages + if (!isset($errorMessages)) { + $className = get_class($this); + $errorMessages = array( + FORM_OK => 'No error', + FORM_ERROR => 'Unknown error', + NO_RECORD => 'Setting both properties (email and hasContactDB) to false in the ' . $className . ' class will result in no email record being sent and no record being inserted into the database. There will be no record that this form was ever filled out.', + INVALID_DB => 'Please set the property hasContactDB to a boolean value in the class ' . $className . ' before continuing', + MISSING_CONSTANT => 'You have failed to set a CONSTANT for the class ' . $className . ' to function properly', + ); + } + + if (!is_null($error->message)) { + $message = $error->message; + } elseif (isset($errorMessages[$error->code])) { + $message = $errorMessages[$error->code]; + } else { + $message = $errorMessages[$error->code]; + $message = $errorMessages[FORM_ERROR]; + } + + echo "
    {$message}
    "; + } + + // }}} + // {{{ processData() + + /** + * Handles how to process the form when submitted + * + * @param array $values Form submitted values + * + * @return array Result of Insert / Update function + * @access protected + */ + protected function processData($values) + { + // Form data used for the insert/update sql queries and + // the form email. + $e = array( + 'mail_ok', + 'user_agent', + 'remote_addr' + ); + $this->setFormData($e); + + + // If no contact db, return true so we can send owner email. + if (!$this->hasContactDB) { + return true; + } + + // 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]); + } + } + } + + // }}} + // {{{ 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}', 'comments'); + $renderer->setElementTemplate(''.$required.'{label}'.$error.'{element}', 'submit_rmv'); + + $renderer->setElementTemplate('{element}', 'captcha_question'); + $renderer->setElementTemplate(''.$required.'{label}
    '.$error.'{element}', 'captcha_rmv'); + } + + // }}} + // {{{ toHTML() + + /** + * Handles how to display the current step the user is at in the form + * + * destroying and resetting the captcha value dis-allows someone from + * re-sending a form on a previous captcha. + * + * @return string form HTML state + * @access public + */ + public function toHTML() + { + $GLOBALS['styleSheets'][] = BASE_URL . 'contactform.css'; + $this->setupRenderers(); + if ($this->validate()) { + $this->captchaQuestion->destroy(); + $this->cleanForm(); + + if ($this->process(array(&$this, 'processData'), $this->mergeFiles)) { + $this->freeze(); + $ret = $this->emailFriend(); + $output = $this->successMsg; + } + $this->sent = true; + } elseif ($this->isSubmitted()) { + $this->captchaQuestion->destroy(); + $this->captchaAnswer->setValue(''); + $output = $this->errorMsg; + $output .= parent::toHTML(); + } else { + $this->captchaQuestion->destroy(); + $this->captchaAnswer->setValue(''); + $output = parent::toHTML(); + } + return $output; + } + + // }}} +} +?> diff --git a/Toolkit/Contacts/assets/.keepme b/Toolkit/Contacts/assets/.keepme new file mode 100644 index 0000000..e69de29 diff --git a/Toolkit/Contacts/database-table-modifiers.sql b/Toolkit/Contacts/database-table-modifiers.sql new file mode 100644 index 0000000..b539d26 --- /dev/null +++ b/Toolkit/Contacts/database-table-modifiers.sql @@ -0,0 +1,46 @@ +CREATE SEQUENCE contact_id_seq + INCREMENT BY 1 + NO MAXVALUE + NO MINVALUE + CACHE 1; + +ALTER TABLE contact ALTER COLUMN id SET DEFAULT nextval('contact_id_seq'::regclass); + +ALTER TABLE ONLY contact + ADD CONSTRAINT contact_pkey PRIMARY KEY (id); + +CREATE INDEX contact_create_date_indx ON contact USING btree (create_date); + +CREATE INDEX contact_email_indx ON contact USING btree (email); + +CREATE INDEX contact_fname_indx ON contact USING btree (fname); + +CREATE UNIQUE INDEX contact_id_indx ON contact USING btree (id); + +CREATE INDEX contact_lname_indx ON contact USING btree (lname); + +CREATE UNIQUE INDEX news_response_id_indx ON contact USING btree (id); + +CREATE UNIQUE INDEX query_db_id_indx ON contact USING btree (id); + +CREATE SEQUENCE contact_inq_id_seq + INCREMENT BY 1 + NO MAXVALUE + NO MINVALUE + CACHE 1; + +ALTER TABLE contact_inq ALTER COLUMN id SET DEFAULT nextval('contact_inq_id_seq'::regclass); + +ALTER TABLE ONLY inq_group + ADD CONSTRAINT inq_group_pkey PRIMARY KEY (id); + +CREATE SEQUENCE inq_group_id_seq + INCREMENT BY 1 + NO MAXVALUE + NO MINVALUE + CACHE 1; + +ALTER TABLE inq_group ALTER COLUMN id SET DEFAULT nextval('inq_group_id_seq'::regclass); + +ALTER TABLE ONLY inq_group + ADD CONSTRAINT inq_group_pkey PRIMARY KEY (id); diff --git a/Toolkit/Contacts/database-tables.sql b/Toolkit/Contacts/database-tables.sql new file mode 100644 index 0000000..1b71879 --- /dev/null +++ b/Toolkit/Contacts/database-tables.sql @@ -0,0 +1,45 @@ +CREATE TABLE contact ( + id integer NOT NULL, + create_date date DEFAULT CURRENT_DATE, + fname text, + lname text, + company text, + address text, + address2 text, + city text, + state text, + zip text, + country text, + phone text, + fax text, + email text, + user_agent text, + remote_addr text, + interest text, + mail_ok boolean DEFAULT false, + visitorguide boolean DEFAULT false, + uidpdf text, + visitorguide_download boolean DEFAULT false, + email_verified boolean DEFAULT true, + contact_type text, + discover text, + member_ok boolean DEFAULT false, + staff boolean DEFAULT false, + comments text, + password text, + verify_password text +); + +CREATE TABLE inq_group ( + id integer NOT NULL, + name text +); + +CREATE TABLE contact_inq ( + id integer NOT NULL, + header text, + pos integer, + description text, + image text, + groupid integer +); diff --git a/Toolkit/Contacts/templates/brochurePage.html b/Toolkit/Contacts/templates/brochurePage.html new file mode 100755 index 0000000..b90d3d5 --- /dev/null +++ b/Toolkit/Contacts/templates/brochurePage.html @@ -0,0 +1,9 @@ + +
    DOWNLOAD: +

    We will email you a link to the PDF version of the {brochure}.

    +
    +
    + {pdfForm:h} +
    +

    ORDER BY MAIL:

    +{contactForm:h} diff --git a/Toolkit/Contacts/templates/compiled/.cvsignore b/Toolkit/Contacts/templates/compiled/.cvsignore new file mode 100644 index 0000000..65fb5e5 --- /dev/null +++ b/Toolkit/Contacts/templates/compiled/.cvsignore @@ -0,0 +1 @@ +* *.* diff --git a/Toolkit/Contacts/templates/compiled/.keepme b/Toolkit/Contacts/templates/compiled/.keepme new file mode 100644 index 0000000..e69de29 diff --git a/Toolkit/Contacts/templates/currentTables/Element.tpl b/Toolkit/Contacts/templates/currentTables/Element.tpl new file mode 100755 index 0000000..595457b --- /dev/null +++ b/Toolkit/Contacts/templates/currentTables/Element.tpl @@ -0,0 +1,14 @@ + + + + * + + + + + +
    {error}
    + + {element} + + diff --git a/Toolkit/Contacts/templates/currentTables/Form.tpl b/Toolkit/Contacts/templates/currentTables/Form.tpl new file mode 100755 index 0000000..f59286a --- /dev/null +++ b/Toolkit/Contacts/templates/currentTables/Form.tpl @@ -0,0 +1,7 @@ +
    + + + {content} +
    + +
    diff --git a/Toolkit/Contacts/templates/currentTables/Group.tpl b/Toolkit/Contacts/templates/currentTables/Group.tpl new file mode 100755 index 0000000..cdd24cf --- /dev/null +++ b/Toolkit/Contacts/templates/currentTables/Group.tpl @@ -0,0 +1,5 @@ + + + {content} + +
    diff --git a/Toolkit/Contacts/templates/currentTables/GroupElement.tpl b/Toolkit/Contacts/templates/currentTables/GroupElement.tpl new file mode 100755 index 0000000..1a4ba27 --- /dev/null +++ b/Toolkit/Contacts/templates/currentTables/GroupElement.tpl @@ -0,0 +1,9 @@ + + + {element} + + * + + {label} + + diff --git a/Toolkit/Contacts/templates/currentTables/Header.tpl b/Toolkit/Contacts/templates/currentTables/Header.tpl new file mode 100755 index 0000000..64ac244 --- /dev/null +++ b/Toolkit/Contacts/templates/currentTables/Header.tpl @@ -0,0 +1,5 @@ + + + {header} + + diff --git a/Toolkit/Contacts/templates/currentTables/RequiredNote.tpl b/Toolkit/Contacts/templates/currentTables/RequiredNote.tpl new file mode 100755 index 0000000..dad5d0b --- /dev/null +++ b/Toolkit/Contacts/templates/currentTables/RequiredNote.tpl @@ -0,0 +1 @@ +* = Required Fields diff --git a/Toolkit/Contacts/templates/direct-list.html b/Toolkit/Contacts/templates/direct-list.html new file mode 100755 index 0000000..eefc842 --- /dev/null +++ b/Toolkit/Contacts/templates/direct-list.html @@ -0,0 +1,29 @@ +

    Your Trip Planner List

    +

    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.

    + + + + {foreach:memberDirectNoEmail,member} + + + + + + {end:} +
    Name + Phone +   +
    {member[memberName]}{member[memberPhone]}Remove
    +

    Request Information by Email from:

    +

    This list of businesses will receive the following information form directly to their email account.

    + + {foreach:memberDirect,member} + + + + + {end:} +
    {member[memberName]}Remove
    +

    Plan Your Trip Information Request Form

    diff --git a/Toolkit/Contacts/templates/emailOwner.tpl b/Toolkit/Contacts/templates/emailOwner.tpl new file mode 100755 index 0000000..e574342 --- /dev/null +++ b/Toolkit/Contacts/templates/emailOwner.tpl @@ -0,0 +1,61 @@ + + + + + {title:h} + + + +

    + + {subject:h} + +

    +

    + + From {fname:h} {lname:h} + +

    + + + + + + + + +
    + + {foreach:formData,v} + + + {if:v[nowrap]} + + {else:} + + {end:} + + {end:} +
    + + {v[label]:h} + + + {v[element]:h} + + {v[element]:h} +
    +
    + + + + +
    + + To ensure the delivery of these e-mails to your inbox, please add {email_from:h} to your e-mail Address Book or Safe List. + +
    +
    + + + diff --git a/Toolkit/Contacts/templates/friendEmail.html b/Toolkit/Contacts/templates/friendEmail.html new file mode 100644 index 0000000..358ded6 --- /dev/null +++ b/Toolkit/Contacts/templates/friendEmail.html @@ -0,0 +1,49 @@ + + + + +

    Dear {fname}

    +

    Your friend {yname} has been to demo.gaslightmedia.com, and thought you might be interested in it.

    +

    Message here.

    +
     

    + + diff --git a/Toolkit/Contacts/templates/pdfDownloadEmail.html b/Toolkit/Contacts/templates/pdfDownloadEmail.html new file mode 100755 index 0000000..6f01198 --- /dev/null +++ b/Toolkit/Contacts/templates/pdfDownloadEmail.html @@ -0,0 +1,19 @@ + + + + + {title:h} + + + + {subject:h} +

    Thank you for requesting the {pdfName} Link. Here is the link to the Adobe PDF version: +

    +

    Brochure ({pdfFileSize})

    +

    Thank you for your interest in {client_info[name]:h}'!

    +

    Sincerely,

    +

    {client_info[name]:h}

    +

    {client_info[url]:h}

    + + + diff --git a/Toolkit/Coupons/Category.php b/Toolkit/Coupons/Category.php new file mode 100644 index 0000000..db77db9 --- /dev/null +++ b/Toolkit/Coupons/Category.php @@ -0,0 +1,99 @@ +_name = $name; + } + + private function _getTableData() + { + $classData = get_object_vars($this); + $dataKeys = array_keys($classData); + $dataValues = array_values($classData); + $func = create_function('$v', 'return substr($v, 1);'); + $newKeys = array_map($func, $dataKeys); + + return array_combine($newKeys, $dataValues); + } + + public function setName($name) + { + $this->_name = $name; + } + + public function getName() + { + return $this->_name; + } + + public function insert(PDO $dbh) + { + $classData = $this->_getTableData(); + unset($classData['id']); + + $sql = Toolkit_Common::createSQLInsert( + 'coupon_category', + array_keys($classData) + ); + + try { + $dbh->beginTransaction(); + Toolkit_Common::processQuery( + $dbh, + 'coupon_category', + $sql, + $classData + ); + + $sql = " + SELECT id + FROM coupon_category + ORDER BY id DESC LIMIT 1"; + + $row = $dbh->query($sql, PDO::FETCH_ASSOC)->fetch(); + + $dbh->commit(); + + $this->_id = $row['id']; + return $this->_id; + } catch (PDOException $e) { + $dbh->rollback(); + return Toolkit_Common::handleError($e); + } + } + + public function update(PDO $dbh) + { + date_default_timezone_set('America/New_York'); +$d = new Date(); +$d->setDate('10-17-2008'); +print_r($d); +die; + $classData = $this->_getTableData(); + $id = $classData['id']; + unset($classData['id']); + + $sql = Toolkit_Common::createSQLUpdate( + 'coupon_category', + array_keys($classData), + array('id = :id') + ); + + try { + $classData['id'] = $id; + return Toolkit_Common::processQuery( + $dbh, + 'coupon_category', + $sql, + $classData + ); + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } +} +?> diff --git a/Toolkit/Coupons/Coupon.php b/Toolkit/Coupons/Coupon.php new file mode 100644 index 0000000..423dc1f --- /dev/null +++ b/Toolkit/Coupons/Coupon.php @@ -0,0 +1,50 @@ +title = $title; + } + + public function setDescription($description) + { + $this->description = $description; + } + + public function setImage($image) + { + $this->image = $image; + } + + public function setExpiration(Date $expiration) + { + $this->expiration = $expiration; + } + + public function getTitle() + { + return $this->title; + } + + public function getDescription() + { + return $this->description; + } + + public function getImage() + { + return $this->image; + } + + public function getExpiration() + { + return $this->expiration; + } +} +?> diff --git a/Toolkit/Coupons/Database/application.sql b/Toolkit/Coupons/Database/application.sql new file mode 100644 index 0000000..e09edc2 --- /dev/null +++ b/Toolkit/Coupons/Database/application.sql @@ -0,0 +1,13 @@ +-- +-- Tables +-- +\i ./tables/coupon_category.sql +\i ./tables/coupons.sql + +-- +-- Procedures +-- + +-- +-- Modules +-- diff --git a/Toolkit/Coupons/Database/tables/coupon_category.sql b/Toolkit/Coupons/Database/tables/coupon_category.sql new file mode 100644 index 0000000..3800073 --- /dev/null +++ b/Toolkit/Coupons/Database/tables/coupon_category.sql @@ -0,0 +1,7 @@ +CREATE TABLE coupon_category +(id INTEGER NOT NULL, + name TEXT NOT NULL, + PRIMARY KEY (id)); + +GRANT ALL ON coupon_category_id_seq TO nobody; +GRANT ALL ON coupon_category TO nobody; diff --git a/Toolkit/Coupons/Database/tables/coupons.sql b/Toolkit/Coupons/Database/tables/coupons.sql new file mode 100644 index 0000000..9d32c1f --- /dev/null +++ b/Toolkit/Coupons/Database/tables/coupons.sql @@ -0,0 +1,22 @@ +CREATE TABLE coupons +(id INTEGER NOT NULL, + title TEXT, + description TEXT, + url TEXT, + sdate DATE NOT NULL, + edate DATE NOT NULL, + expiration DATE NOT NULL, + category INTEGER + REFERENCES coupon_category (id) + ON UPDATE CASCADE + ON DELETE CASCADE, + active BOOLEAN NOT NULL DEFAULT FALSE, + member INTEGER + REFERENCES member (member_id) + ON UPDATE CASCADE + ON DELETE CASCADE, + image TEXT, + PRIMARY KEY (id)); + +GRANT ALL ON coupons_id_seq TO nobody; +GRANT ALL ON coupons TO nobody; diff --git a/Toolkit/Coupons/ICoupon.php b/Toolkit/Coupons/ICoupon.php new file mode 100644 index 0000000..570e210 --- /dev/null +++ b/Toolkit/Coupons/ICoupon.php @@ -0,0 +1,7 @@ + diff --git a/Toolkit/Coupons/IFactory.php b/Toolkit/Coupons/IFactory.php new file mode 100644 index 0000000..def769d --- /dev/null +++ b/Toolkit/Coupons/IFactory.php @@ -0,0 +1,6 @@ + diff --git a/Toolkit/Coupons/MemberCoupon.php b/Toolkit/Coupons/MemberCoupon.php new file mode 100644 index 0000000..8450017 --- /dev/null +++ b/Toolkit/Coupons/MemberCoupon.php @@ -0,0 +1,101 @@ +title = $data['title']; + $this->image = $data['image']; + if (isset($data['description'])) { + $this->description = $data['description']; + } + if (isset($data['expiration'])) { + $this->expiration = $data['expiration']; + } + } + + public function setCategory ($category) + { + settype($category, 'integer'); + + $this->category = $category; + } + + public function getCategory() + { + return $this->category; + } + + public function insert(PDO $dbh) + { + $classData = get_object_vars($this); + $classData['expiration'] = $this->expiration->format('%m-%d-%Y'); + unset($classData['id']); + + $sql = Toolkit_Common::createSQLInsert( + 'coupons', + array_keys($classData) + ); + + try { + $dbh->beginTransaction(); + Toolkit_Common::processQuery( + $dbh, + 'coupons', + $sql, + $classData + ); + + $sql = " + SELECT id + FROM coupons + ORDER BY id DESC LIMIT 1"; + + $row = $dbh->query($sql, PDO::FETCH_ASSOC)->fetch(); + + $dbh->commit(); + + $this->id = $row['id']; + return $this->id; + } catch (PDOException $e) { + $dbh->rollback(); + return Toolkit_Common::handleError($e); + } + } + + public function update(PDO $dbh) + { + $classData = get_object_vars($this); + $classData['expiration'] = $this->expiration->format('%m-%d-%Y'); + $id = $classData['id']; + unset($classData['id']); + + $sql = Toolkit_Common::createSQLUpdate( + 'coupons', + array_keys($classData), + array('id = :id') + ); + + try { + $classData['id'] = $id; + return Toolkit_Common::processQuery( + $dbh, + 'coupons', + $sql, + $classData + ); + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } +} +?> diff --git a/Toolkit/Coupons/MemberFactory.php b/Toolkit/Coupons/MemberFactory.php new file mode 100644 index 0000000..4bb9241 --- /dev/null +++ b/Toolkit/Coupons/MemberFactory.php @@ -0,0 +1,9 @@ + diff --git a/Toolkit/DataGridBuilder.php b/Toolkit/DataGridBuilder.php new file mode 100644 index 0000000..0666dcf --- /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.13 2009/09/16 00:07:44 jamie 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..1bab552 --- /dev/null +++ b/Toolkit/Database.php @@ -0,0 +1,123 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @version CVS: $Id: Database.php,v 1.4 2009/11/15 19:06:21 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/FlexyDataGridBuilder.php b/Toolkit/FlexyDataGridBuilder.php new file mode 100644 index 0000000..d41e241 --- /dev/null +++ b/Toolkit/FlexyDataGridBuilder.php @@ -0,0 +1,222 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @version CVS: $Id: FlexyDataGridBuilder.php,v 1.13 2009/12/29 14:27:55 jamie 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; + * + * + * + * {row[img]} src= + * + * + * @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, + $template = null + ) { + $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); + $tEngine = $renderer->getContainer(); + + $pathToTemplate = $tEngine->options['templateDir'][0]; + + if ( !is_null($template) + && file_exists("$pathToTemplate/$template") + ) { + $tEngine->compile($template); + } elseif (isset($this->template) + && file_exists($pathToTemplate . $this->template) + ) { + $tEngine->compile($this->template); + } else { + throw new RuntimeException('Template not available'); + } + + // 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..c9e8d2e --- /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.6 2009/08/31 17:43:48 jamie 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..20bfbaf --- /dev/null +++ b/Toolkit/FormBuilder.php @@ -0,0 +1,1197 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @version CVS: $Id: FormBuilder.php,v 1.39 2010/01/30 17:05:35 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 . 'Toolkit/Forms/templates/tables/'; + $this->dbh = Toolkit_Database::getInstance(); + + $GLOBALS['styleSheets'][] = BASE_URL . 'contactform.css'; + + $GLOBALS['scripts'][] + = GLM_APP_BASE_URL . 'libjs/contactform-1.1.js'; + } + + // }}} + + // {{{ 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 + * + * + * + * + * * + * + * + * + * + * + *
    {error}
    + * + * {element} + * + * + *
    + * + * # Form.tpl + * + *
    + * + * + * {content} + *
    + * + *
    + *
    + * + * # GroupElement.tpl + * + * + * + * {element} + * + * * + * + * {label} + * + * + * + * + * # Group.tpl + * + * + * + * {content} + * + *
    + *
    + * + * # Header.tpl + * + * + * + * {header} + * + * + * + * + * # RequiredNote.tpl + * + * * Denotes required field + * + * + * @param array $groups any groups that need to be rendered + * via the groupElementTemplate and groupTemplate + * + * @return void + * @access protected + */ + protected function setupRenderers(array $groups = array()) + { + if (is_dir($this->template)) { + if ($dh = opendir($this->template)) { + while (($file = readdir($dh)) !== false) { + // Ignore current dir and parent dir. + if ($file != '..' && $file != '.' && $file != 'CVS') { + $baseName = reset(explode('.', $file)); + // Ignores swp files. + if (!empty($baseName)) { + $method = "set{$baseName}Template"; + $template = file_get_contents($this->template . $file); + $renderer =& $this->defaultRenderer(); + if ( $method != 'setGroupTemplate' + && $method != 'setGroupElementTemplate' + ) { + if (method_exists($renderer, $method)) { + $renderer->$method($template); + } + } else { + // apply the templates to any defined groups + foreach ($groups as $k) { + $renderer->$method($template, $k); + } + } + } + } + } + closedir($dh); + } + } + } + + // }}} + // {{{ useCaptcha() + + /** + * Set if we need to use a captcha in this form or not + * + * @param boolean $useCaptcha true/false to use a captcha with the form + * + * @return void + * @access public + */ + public function useCaptcha($useCaptcha) + { + $this->useClueTip(); + $this->useCaptcha = $useCaptcha; + } + + // }}} + // {{{ useClueTip() + + /** + * Set if we need to use the JS cluetip + * + * @param boolean $useCaptcha include cluetip resources or not + * + * @return void + * @access public + */ + public function useClueTip() + { + $GLOBALS['styleSheets'][] + = GLM_APP_BASE_URL . 'libjs/cluetip/jquery.cluetip.css'; + $GLOBALS['scripts'][] + = GLM_APP_BASE_URL . 'libjs/cluetip/jquery.cluetip.js'; + $GLOBALS['scripts'][] + = GLM_APP_BASE_URL . 'libjs/cluetip/lib/jquery.hoverIntent.js'; + $GLOBALS['scripts'][] + = GLM_APP_BASE_URL . 'libjs/cluetip/lib/jquery.bgiframe.min.js'; + } + + // }}} + // {{{ show() + + /** + * Shows the form + * + * @return void + * @access public + */ + public function show() + { + Toolkit_Common::show(); + } + + // }}} +} +?> diff --git a/Toolkit/Forms/Rules/Date.php b/Toolkit/Forms/Rules/Date.php new file mode 100644 index 0000000..8b899a3 --- /dev/null +++ b/Toolkit/Forms/Rules/Date.php @@ -0,0 +1,64 @@ + '%m-%d-%Y') is the default + * + * @param string $value the date array to validate + * @param array $options options used to dictate validation of the date + + * @return bool if the string could correctly be validated as a date. + * @access public + * @see Validate::date() + */ + function validate($value, array $options) + { + $month = !isset($options['group']) + ? $value['m'] + : $value[$options['group']]['m']; + $day = !isset($options['group']) + ? $value['d'] + : $value[$options['group']]['d']; + $year = !isset($options['group']) + ? $value['Y'] + : $value[$options['group']]['Y']; + + if (isset($options['allowEmpty']) + && $options['allowEmpty'] + && empty($month) + && empty($day) + && empty($year) + ) { + return true; + } + + unset($options['group'], $options['allowEmpty']); + + $day = str_pad($day, 2, '0', STR_PAD_LEFT); + $month = str_pad($month, 2, '0', STR_PAD_LEFT); + + return Validate::date("$month-$day-$year", $options); + } + + function getValidationScript($options = null) + { + return array('', true); + } +} + +HTML_QuickForm::registerRule( + 'Date', + 'rule', + 'Toolkit_Forms_Rules_Date', + BASE . 'Toolkit/Forms/Rules/Date.php' +); +?> diff --git a/Toolkit/Forms/templates/tables/Element.tpl b/Toolkit/Forms/templates/tables/Element.tpl new file mode 100644 index 0000000..595457b --- /dev/null +++ b/Toolkit/Forms/templates/tables/Element.tpl @@ -0,0 +1,14 @@ + + + + * + + + + + +
    {error}
    + + {element} + + diff --git a/Toolkit/Forms/templates/tables/Form.tpl b/Toolkit/Forms/templates/tables/Form.tpl new file mode 100644 index 0000000..09f344b --- /dev/null +++ b/Toolkit/Forms/templates/tables/Form.tpl @@ -0,0 +1,7 @@ +
    + + + {content} +
    + +
    diff --git a/Toolkit/Forms/templates/tables/Group.tpl b/Toolkit/Forms/templates/tables/Group.tpl new file mode 100644 index 0000000..cdd24cf --- /dev/null +++ b/Toolkit/Forms/templates/tables/Group.tpl @@ -0,0 +1,5 @@ + + + {content} + +
    diff --git a/Toolkit/Forms/templates/tables/GroupElement.tpl b/Toolkit/Forms/templates/tables/GroupElement.tpl new file mode 100644 index 0000000..1a4ba27 --- /dev/null +++ b/Toolkit/Forms/templates/tables/GroupElement.tpl @@ -0,0 +1,9 @@ + + + {element} + + * + + {label} + + diff --git a/Toolkit/Forms/templates/tables/Header.tpl b/Toolkit/Forms/templates/tables/Header.tpl new file mode 100644 index 0000000..64ac244 --- /dev/null +++ b/Toolkit/Forms/templates/tables/Header.tpl @@ -0,0 +1,5 @@ + + + {header} + + diff --git a/Toolkit/Forms/templates/tables/RequiredNote.tpl b/Toolkit/Forms/templates/tables/RequiredNote.tpl new file mode 100644 index 0000000..525ef33 --- /dev/null +++ b/Toolkit/Forms/templates/tables/RequiredNote.tpl @@ -0,0 +1 @@ +* Denotes required field diff --git a/Toolkit/INavigation.php b/Toolkit/INavigation.php new file mode 100644 index 0000000..9e8f4cf --- /dev/null +++ b/Toolkit/INavigation.php @@ -0,0 +1,12 @@ + diff --git a/Toolkit/Image/Server.php b/Toolkit/Image/Server.php new file mode 100755 index 0000000..7056ef4 --- /dev/null +++ b/Toolkit/Image/Server.php @@ -0,0 +1,370 @@ + + * @copyright 2008 Steve Sutton + * @license Gaslight Media + * @version CVS: $Id: Server.php,v 1.15 2009/09/29 18:37:48 matrix Exp $ + * @link http://demo.gaslightmedia.com + */ + +/** + * Description for define + */ +define('IS_VALIDATE_SECRET', 'Glm0IS1secreT'); + +/** + * Description for define + */ +define('IS_SUBMIT_URL', 'is0.gaslightmedia.com/submit.phtml'); + +/** + * Toolkit_Image_Server + * + * Class for implementation of the image server process Chuck has + * setup for is0.gaslightmedia.com + * Uses Curl PHP Library to upload images to the server + * + * @category Images + * @package Toolkit_Image + * @author Steve Sutton + * @copyright 2008 Steve Sutton + * @license Gaslight Media + * @link http://demo.gaslightmedia.com + */ +class Toolkit_Image_Server +{ + // {{{ properties + + /** + * OwnerID for the Image Server User + * @var string + * @access protected + */ + protected $OwnerID; + + /** + * Owner Password + * @var string + * @access protected + */ + protected $OwnerPW; + + /** + * DOMDocument Object + * @var unknown + * @access protected + */ + protected $xml; + + // }}} + + // {{{ __construct() + + /** + * __construct + * + * @return void + * @access public + */ + function __construct() + { + $this->OwnerID = IS_OWNER_ID; + $this->OwnerPW = IS_OWNER_PW; + } + + // }}} + + // {{{ buildImageServerXML() + + /** + * buildImageServerXML + * + * Create the xml for the FileServerRequest + * + * @param string $fileName File to upload or delete + * @param unknown $type Upload or Delete + * + * @return string xml content + * @access public + */ + function buildImageServerXML($fileName, $type) + { + $xml = new DOMDocument('1.0'); + $xml->formatOutput = true; + $FileServerRequest = $xml->createElement('FileServerRequest'); + $FileServerRequest->setAttribute('version', '1.0'); + // AccessRequest part + $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 part + $File = $xml->createElement('File'); + switch ($type) { + case "Upload": + $FileAction = $xml->createElement('FileAction', 'Submit'); + $DeliveryMethod = $xml->createElement('DeliveryMethod', 'Submit'); + $FieldName = $xml->createElement('FieldName', 'file_upload'); + $File->appendChild($FileAction); + $File->appendChild($DeliveryMethod); + $File->appendChild($FieldName); + $FileServerRequest->appendChild($File); + $size = filesize($_FILES[$fileName]['tmp_name']); + $validStr = md5($this->OwnerID.$this->OwnerPW.IS_VALIDATE_SECRET); + break; + case "URL": + $FileAction = $xml->createElement('FileAction', 'Submit'); + $DeliveryMethod = $xml->createElement('DeliveryMethod', 'URL'); + $Src = $xml->createElement('Src', $fileName); + $File->appendChild($FileAction); + $File->appendChild($DeliveryMethod); + $File->appendChild($Src); + $FileServerRequest->appendChild($File); + $size = strlen($fileName); + $validStr = md5($this->OwnerID.$this->OwnerPW.IS_VALIDATE_SECRET); + break; + case "Delete": + $FileAction = $xml->createElement('FileAction', 'Delete'); + $File->appendChild($FileAction); + $FileName = $xml->createElement('FileName', $fileName); + $File->appendChild($FileName); + $FileServerRequest->appendChild($File); + $validStr = md5($this->OwnerID.$this->OwnerPW.IS_VALIDATE_SECRET); + break; + } + // validation part + $Validation = $xml->createElement('Validation', $validStr); + $FileServerRequest->appendChild($Validation); + $xml->appendChild($FileServerRequest); + return $xml->saveXML($xml); + } + + // }}} + + // {{{ imageDelete() + + /** + * imageDelete + * + * Delete an image from the image server + * + * @param unknown $name Image name + * + * @return unknown image name + * @access public + */ + function imageDelete($name) + { + if ($name) { + $request = $this->buildImageServerXML($name, 'Delete'); + $ch = curl_init(); + $fileData = array( + 'request' => $request + ); + $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); + $xmlDoc = new DOMDocument; + $response = str_replace("", "", $response); + $xmlDoc->loadXML($response); + $SuccessCode = $this->xmlPathContent( + $xmlDoc, + '/FileServerResponse/ReplyStatus/SuccessCode' + ); + $Message = $this->xmlPathContent( + $xmlDoc, + '/FileServerResponse/ReplyStatus/Message' + ); + $Owner = $this->xmlPathContent( + $xmlDoc, + '/FileServerResponse/File/Owner' + ); + $StoredName = $this->xmlPathContent( + $xmlDoc, + '/FileServerResponse/File/StoredName' + ); + $StoredSize = $this->xmlPathContent( + $xmlDoc, + '/FileServerResponse/File/StoredSize' + ); + $MediaType = $this->xmlPathContent( + $xmlDoc, + '/FileServerResponse/File/MediaType' + ); + return $Message; + } + } + + // }}} + // {{{ imageUpload() + + /** + * imageUpload + * + * Upload image to server + * + * @param string $name Form field name of image + * + * @return string Image name + * @access public + */ + function imageUpload($name) + { + $fileType = null; + if (preg_match("/^http/", $name)) { + $fileType = 'URL'; + } elseif (is_array($_FILES[$name])) { + $fileType = 'Upload'; + } + if ($fileType) { + $request = $this->buildImageServerXML($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); + $xmlDoc = new DOMDocument; + $response = str_replace("", "", $response); + $xmlDoc->loadXML($response); + $SuccessCode = $this->xmlPathContent( + $xmlDoc, + '/FileServerResponse/ReplyStatus/SuccessCode' + ); + $Message = $this->xmlPathContent( + $xmlDoc, + '/FileServerResponse/ReplyStatus/Message' + ); + $Owner = $this->xmlPathContent( + $xmlDoc, + '/FileServerResponse/File/Owner' + ); + $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 Exception('Image Server Error said:'.$response); + throw new PEAR_Exception('Image Server Error said:'.$response); + 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)) { + throw new PEAR_Exception('Invalid URI for the image'); + exit; + } + + $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..8b4b26f --- /dev/null +++ b/Toolkit/Logger.php @@ -0,0 +1,117 @@ + + * @copyright 2010 Jamie Kahgee + * @license http://www.gaslightmedia.com/ Gaslightmedia + * @version CVS: $Id: Logger.php,v 1.3 2010/01/29 11:48:47 jamie 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 +{ + + /** + * 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() + { + $errorLogName = (ERROR_LOG_NAME != '') ? constant(ERROR_LOG_NAME) : ''; + + $logger =& Log::singleton( + ERROR_LOG_TYPE, + $errorLogName, + ERROR_LOG_IDENT, + $GLOBALS['ERROR_LOG_CONF'], + constant(ERROR_LOG_LEVEL) + ); + + return $logger; + } + + /** + * 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(); + } + + switch ($errno) { + case E_ERROR : + case E_USER_ERROR : + $logger->emerg($errstr. ' in ' . $errfile . ' at line ' . $errline, PEAR_LOG_EMERG); + include BASE . '404.html'; + exit(1); + break; + + case E_WARNING : + CASE E_USER_WARNING : + $logger->warning($errstr. ' in ' . $errfile . ' at line ' . $errline, PEAR_LOG_WARNING); + break; + + case E_NOTICE : + case E_USER_NOTICE : + $logger->notice($errstr. ' in ' . $errfile . ' at line ' . $errline, PEAR_LOG_NOTICE); + break; + + default : + $logger->info($errstr. ' in ' . $errfile . ' at line ' . $errline, PEAR_LOG_INFO); + break; + } + + // return FALSE and let the normal error handler continue + return false; + } +} +?> diff --git a/Toolkit/Navigation.php b/Toolkit/Navigation.php new file mode 100644 index 0000000..0946b5e --- /dev/null +++ b/Toolkit/Navigation.php @@ -0,0 +1,58 @@ +menu->setMenu($navStructure); + $this->menu->setMenuType($type); + + $this->setCurrentIndex(); + $this->setNavTemplates(); + + $this->menu->render($this->rEngine); + return $this->rEngine->toHtml(); + } + + // }}} + // {{{ setNavTemplates() + + abstract protected function setNavTemplates(); + + // }}} +} +?> diff --git a/Toolkit/Page.php b/Toolkit/Page.php new file mode 100755 index 0000000..49ebe14 --- /dev/null +++ b/Toolkit/Page.php @@ -0,0 +1,563 @@ + + * @copyright 2009 Gaslight Media + * @license http://demo.gaslightmedia.com Gaslight Media + * @version CVS: $Id: Page.php,v 1.61 2010/02/02 17:15:32 jamie Exp $ + * @link http://demo.gaslightmedia.com + */ + +/** + * Page for Error Doc + */ +define("ERROR_DOCUMENT", "404.html"); + +/** + * The home page template + */ +define("HOME_TEMPLATE", "template.html"); + +/** + * inside page template + */ +define("INSIDE_TEMPLATE", "template.html"); + +/** + * Template for the error doc + */ +define("ERROR_DOCUMENT_TEMPLATE", "404-template.html"); + +/** + * page title default + */ +define("PAGE_TITLE", "Gaslight Media Demo Site"); + + +/** + * Toolkit_Page + * + * A class Object for use with merging into the flexy template for output. + * Sets up the $page object used for merging with the flexy template + * to output the toolbox and members admin content + * + * @category Toolkit + * @package Toolkit_Page + * @author Steve Sutton + * @copyright 2009 Gaslight Media + * @license http://demo.gaslightmedia.com Gaslight Media + * @link http://demo.gaslightmedia.com + */ +class Toolkit_Page +{ + // {{{ Properties + + /** + * used on img src and style href tags + * @var $baseURL + * @access public + */ + public $baseURL; + + /** + * meta tag description element + * @var $metaTags + * @access public + */ + public $metaTags; + + /** + * Array of scripts with absolute paths + * @var $scripts array + * @access public + */ + public $scripts = array(); + + /** + * Array of style sheet with absolute paths + * @var $styles array + * @access public + */ + public $styles = array(); + + /** + * title tag node + * @var $title + * @access public + */ + public $title; + + /** + * The main content of website + * @var $toolboxContent + * @access public + */ + public $toolboxContent; + + // }}} + // {{{ __construct() + + /** + * __construct + * + * @param object $toolbox An instance of a valid GLM_TOOLBOX Object + * + * @return void + * @access public + */ + public function __construct(GLM_TEMPLATE $toolbox) + { + // determine the base url to use (for images and stylesheet urls) + $this->baseURL + = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') + ? BASE_SECURE_URL + : BASE_URL; + + if (isset($_GET['member_id']) && ctype_digit($_GET['member_id'])) { + // Member profile pages can't have search page title tags + $this->title = SITENAME; + } else { + // set the title of the page + $this->title = $toolbox->title() + ? $toolbox->title() . SITENAME + : SITENAME; + } + + // set the metaTags + $this->metaTags = $toolbox->meta_tags(); + + // determine the base url to use (for GLM_APP_BASE_URL) + $this->glmAppBaseURL + = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') + ? BASE_SECURE_URL + : GLM_APP_BASE_URL; + + // used in class + $this->toolbox = $toolbox; + $this->sitemapURL = $this->baseURL . 'site-map'; + + // get top parent id if needed + $topParent = $toolbox->get_top_parent($toolbox->catid); + + // true if on home page + $this->isHomePage = (HOME_ID == $toolbox->catid); + + // pageTitle + $this->pageTitle = $toolbox->get_catheader($topParent, $toolbox->DB); + + // Resources needed for every page. + $GLOBALS['styleSheets'][] = $this->baseURL . 'stylesNew.css'; + $GLOBALS['scripts'][] + = $this->glmAppBaseURL . 'libjs/jquery-1.3.2.min.js'; + $GLOBALS['scripts'][] = $this->baseURL . 'libjs/newsletterSignup.js'; + + // bread crumb navigation + $this->breadCrumbs = $toolbox->get_bread_crumbs($toolbox->catid); + + // main nav + $this->mainNav = $toolbox->get_main_nav(); + + // sideNav + if ($toolbox->catid != HOME_ID) { + $this->sideNav = $toolbox->get_side_nav($topParent); + } else { + $this->sideNav = ''; + } + + // urls used in the template set using get_seo_url + $this->glmAssociate = $toolbox->get_seo_url(2); + $this->contactGLM = $toolbox->get_seo_url(10); + $this->servicesOffered = $toolbox->get_seo_url(81); + $this->aboutGLM = $toolbox->get_seo_url(86); + $this->newsletterAction = $toolbox->get_seo_url(10); + + $this->tripPlannerCount = count($_SESSION['wish_list']); + $this->tripPlannerUrl = $toolbox->get_seo_url(MEMBER_SESSION_PAGE); + // check if define for HOME_EVENTS is set + if (defined("HOME_EVENTS") && HOME_EVENTS && $toolbox->catid == HOME_ID) { + $this->events($toolbox); + } + + // check if define for HOME_HEADLINES is set + if ( defined("HOME_HEADLINES") + && HOME_HEADLINES + && $this->isHomePage + ) { + $this->headlines($toolbox); + } + + // check if define for HOME_NEWS is set + if (defined("HOME_NEWS") && HOME_NEWS) { + $this->news($toolbox); + } + + // check if define for WEATHER is set + if (defined("WEATHER") && WEATHER) { + $this->hasWeather = true; + $this->weather(); + } + + // check if define for GOOGLE_SEARCH is set + if (defined("GOOGLE_SEARCH") && GOOGLE_SEARCH) { + $this->googleSearch(); + } + + // check if define for BANNERS is set + if (defined("BANNERS") && BANNERS) { + $this->banners(&$toolbox); + } + + if ( defined("ROTATING_IMAGES") + && ROTATING_IMAGES + && in_array($toolbox->catid, array(108)) + ) { + $this->_rotatingImages(); + } + } + + // }}} + + // {{{ _rotatingImages() + + private function _rotatingImages() + { + $nodesIterator = new Toolkit_RotatingImages_NodesIterator(); + $nodesIterator->findAll(Toolkit_Database::getInstance()); + $is = new Toolkit_Image_Server(); + $decorator = new Toolkit_RotatingImages_LiveDecorator(); + foreach ($nodesIterator as $v) { + if ($v->getActive()) { + if ($v instanceof Toolkit_RotatingImages_Anchor) { + $nodeDecorator + = new Toolkit_RotatingImages_AnchorDecorator($v); + $decorator->add($nodeDecorator); + } elseif ($v instanceof Toolkit_RotatingImages_Image) { + $nodeDecorator + = new Toolkit_RotatingImages_ImageDecorator($v); + $decorator->add($nodeDecorator); + } + } + } + + $this->rotatingImages = $decorator->getRotatingJavascript( + Toolkit_Database::getInstance() + ); + $this->rotatingImages .= $decorator->toHtml($is); + } + + // }}} + + // {{{ banners() + + /** + * Add Banner module + * + * @param unknown &$toolbox Toolbox object + * + * @return void + * @access public + */ + public function banners(&$toolbox) + { + $dbh = Toolkit_Database::getInstance(); + $banners =& Toolkit_Banners_BannersIterator::create('Bottom'); + if (defined('MEMBER_DB') && MEMBER_DB) { + $categoriesIterator = Toolkit_Members_CategoriesIterator::create(); + $banners->fetchAllAvailable( + $dbh, + $categoriesIterator, + $toolbox->catid + ); + } else { + $banners->fetchAllAssignedToPage($dbh, $toolbox->catid); + } + + $availableBanners = $banners->getAvailable(); + + // Are there any banners even available + if (count($availableBanners)) { + $decorators = Toolkit_Banners_RotatingBannersDecorator::create(); + foreach ($availableBanners as $i) { + $decorator = Toolkit_Banners_HorizontalDecorator::create($i); + $decorators->add($decorator); + } + + $this->hasBanner = count($decorators->getIterator()); + $this->bannerAds = $decorators->toHtml( + $dbh, + new Toolkit_Image_Server(), + $toolbox->catid + ); + } + } + + // }}} + + // {{{ createErrorDocument() + + /** + * Create the error document page + * + * @return void + * @access public + */ + function createErrorDocument() + { + $this->baseURL = BASE_URL; + $this->homeURL = $this->toolbox->get_seo_url(HOME_ID);; + // Initiate HTML_Template_Flexy. + $template = new HTML_Template_Flexy($GLOBALS['flexyOptions']); + + // Create a template object for the 404 content part + $errorDocumentTemplate = new HTML_Template_Flexy($GLOBALS['flexyOptions']); + $errorDocumentTemplate->compile(ERROR_DOCUMENT_TEMPLATE); + $errorDocumentContents = $errorDocumentTemplate->bufferedOutputObject($this); + + // set defaults + $this->toolboxContent = $errorDocumentContents; + $this->title = '404 Not Found - '.PAGE_TITLE; + $this->hasHeadlines = false; + $this->hasAreaEvents = false; + $this->hasNews = false; + $this->sideNav = null; + $this->mainNav = $this->toolbox->get_main_nav(); + $this->hasWeather = false; + $this->isHomePage = false; + $this->sitemapURL = false; + + // compile the flexy template + $template->compile(INSIDE_TEMPLATE); + + // Merge compiled template with the object. + $fileContents = $template->bufferedOutputObject($this); + file_put_contents(BASE.ERROR_DOCUMENT, $fileContents); + } + + // }}} + + // {{{ events() + + /** + * Add Event module + * + * @param object $toolbox Toolbox object + * + * @return void + * @access public + */ + public function events($toolbox) + { + $events = new Toolkit_Events_Display( + Toolkit_Database::getInstance() + ); + $this->events = $events->getHomeEvents(); + $this->hasEvents = !empty($this->events); + $this->eventsUrl = $toolbox->get_seo_url(EVENT_PAGE); + $GLOBALS['scripts'][] + = $this->glmAppBaseURL . 'libjs/plugins/cycle/2.73/jquery.cycle.all.min.js'; + $GLOBALS['scripts'][] + = $this->baseURL . 'Toolkit/Events/libjs/eventRotate.js'; + $GLOBALS['styleSheets'][] + = $this->baseURL . 'event.css'; + } + + // }}} + + // {{{ generateSiteMap() + + /** + * Generate the site map page + * + * @return string HTML sitemap string + * @access public + */ + function generateSiteMap() + { + $WHERE = ''; + if (defined(MEMBERS_CATEGORY) && defined(MEMBERS_DB)) { + $WHERE = "AND id != ".MEMBERS_CATEGORY; + } + $sql = " + SELECT * + FROM bus_category + WHERE active = 't' + $WHERE + ORDER BY parent, pos"; + + $data = $this->toolbox->DB->db_auto_get_data($sql); + if (is_array($data)) { + foreach ($data as $key => $val) { + $threads[] = array( + "id" => $val['id'], + 'category' => strip_tags($val['category']), + 'type' => $val['type'], + 'parent' => $val['parent'], + 'closed' => false); + } + } + if (is_array($threads)) { + $myThread = new Toolkit_SiteMap($this->toolbox); + //sort threads by parent + $converted = $myThread->sortChilds($threads); + //print the threads + $out .= $myThread->convertToThread($converted, $converted[0]); + } + return '
    + '.$out.' +
    '; + } + + // }}} + + // {{{ getToolboxName($id) + + /** + * grab the navigation name for the id + * + * @param integer $id id for bus_category table + * + * @return string page nav name + * @access public + */ + function getToolboxName($id) + { + return $this->toolbox->get_catheader($id, $this->toolbox->DB); + } + + // }}} + // {{{ getToolboxUrl($id) + + /** + * grab the navigation url for the id + * + * @param integer $id id for bus_category table + * + * @return string url + * @access public + */ + function getToolboxUrl($id) + { + return $this->toolbox->get_seo_url($id); + } + + // }}} + + // {{{ googleSearch() + + /** + * Add Google Search module + * + * @return void + * @access public + */ + public function googleSearch() + { + $this->gSearchOn = false; + $this->isHomePage = false; + if (isset($_REQUEST['query']) && $_REQUEST['query']) { + $this->gSearchOn = true; + $query = urlencode($_REQUEST['query']); + $GLOBALS['styleSheets'][] = BASE_URL.'gsearch.css'; + $GLOBALS['scripts'][] + = 'http://www.google.com/uds/api?file=uds.js&v=1.0&key='.GSEARCH_API; + $GLOBALS['scripts'][] = BASE_URL . 'libjs/gsearch.php?query='.$query; + } + } + + // }}} + + // {{{ headlines() + + /** + * grab the home page headlines + * + * @param object $toolbox Toolbox object + * + * @return void + * @access public + */ + public function headlines($toolbox) + { + // get headlines aka 'Quick Links' + $this->headlines = $toolbox->get_headlines(); + // boolean for if toolbox has headlines + $this->hasHeadlines = !empty($this->headlines); + } + + // }}} + + // {{{ isPhotoGalleryPage() + + /** + * Check if this page has photo gallery in it + * + * @return boolean If this page has a photo gallery assigned to it + * @access public + */ + function isPhotoGalleryPage() + { + $sql = " + SELECT photocat_id + FROM photo_category_bus + WHERE buscat_id = {$this->toolbox->catid}"; + if ($pData = $this->toolbox->DB->select($sql)) { + return true; + } + return false; + } + // }}} + + // {{{ news() + + /** + * grab the home page newsletter/press info + * + * @param object $toolbox Toolbox object + * + * @return void + * @access public + */ + public function news($toolbox) + { + if (HOME_ID == $toolbox->catid) { + $this->news = $toolbox->get_news(); + $this->hasNews = (!empty($this->news)); + } else { + $this->hasNews = false; + } + } + + // }}} + + // {{{ weather() + + /** + * Add Weather module + * + * @return void + * @access public + */ + public function weather() + { + $weather = new Toolkit_Weather(); + if (PEAR::isError($weather->currentCond)) { + return false; + } + $this->weather = $weather->currentCond['weather']; + $this->tempF = $weather->currentCond['temp_f']; + $this->iconUrlName = $weather->currentCond['icon_url_name']; + $this->location = $weather->currentCond['location']; + } + + // }}} +} +?> diff --git a/Toolkit/ShortURL.php b/Toolkit/ShortURL.php new file mode 100755 index 0000000..7189021 --- /dev/null +++ b/Toolkit/ShortURL.php @@ -0,0 +1,127 @@ + + * @copyright 2009 Gaslight Media + * @license Gaslight Media + * @version CVS: $Id: ShortURL.php,v 1.3 2009/06/24 01:30:02 matrix Exp $ + * @link <> + */ + +/** + * Toolkit_ShortURL + * + * Integration of Toolbox with creation of ShortURL + * the url rewrite happens with one line of code in .htaccess + * RewriteRule ^([A-Za-z0-9_-]*)$ index.php?page=$1 [L] + * index page checks for $_GET['page'] and then calls + * getShortUrlId to get the page's catid. If not found it + * defaults to HOME_ID + * + * @category Toolkit + * @package Toolkit_ShortURL + * @author Steve Sutton + * @copyright 2009 Gaslight Media + * @license Gaslight Media + * @version Release: @package_version@ + * @link <> + */ +class Toolkit_ShortURL +{ + // {{{ Class Properties + /** + * PDO Global object + * @var string + * @access protected + */ + public $dbh; + // }}} + + // {{{ __construct() + + /** + * __construct() + * + * @param object &$dbh from setup.phtml + * + * @return void + * @access public + */ + function __construct(&$dbh) + { + $this->dbh = $dbh; + } + + // }}} + // {{{ getShortUrl() + + /** + * getShortUrl() + * + * grab the shorturl from bus_category table + * else return false + * + * @param string $id bus_category id + * + * @return mixed ShortURL from bus_category + * @access public + */ + function getShortUrl($id) + { + $sql = " + SELECT short_url + FROM bus_category + WHERE id = :id"; + try { + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(":id", $id, PDO::PARAM_INT); + $stmt->execute(); + return $stmt->fetchColumn(); + } catch(PDOException $e) { + Toolkit_Common::handleError($e); + } + return false; + } + + // }}} + // {{{ getShortUrlId() + + /** + * getShortUrlId() + * + * grab the id from bus_category table + * else return false + * + * @param string $short_url bus_category short_url + * + * @return mixed catid for page or HOME_ID if not found + * @access public + */ + function getShortUrlId($short_url) + { + $sql = " + SELECT id + FROM bus_category + WHERE short_url = :short_url"; + try { + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(":short_url", $short_url, PDO::PARAM_STR); + $stmt->execute(); + return $stmt->fetchColumn(); + } catch(PDOException $e) { + Toolkit_Common::handleError($e); + } + return HOME_ID; + } + + // }}} +} +?> diff --git a/Toolkit/SiteMap.php b/Toolkit/SiteMap.php new file mode 100755 index 0000000..1b84c68 --- /dev/null +++ b/Toolkit/SiteMap.php @@ -0,0 +1,156 @@ + + * @copyright 2009 Gaslight Media + * @license Gaslight Media + * @version CVS: $Id: SiteMap.php,v 1.6 2009/06/17 23:01:20 jamie Exp $ + * @link <> + */ + +/** + * Toolkit_SiteMap + * + * Generate a sitemap for the site + * need to remove members only pages and other pages you + * don't want viewed by public + * + * @category Toolkit + * @package Toolkit_SiteMap + * @author Steve Sutton + * @copyright 2009 Gaslight Media + * @license Gaslight Media + * @link <> + */ +class Toolkit_SiteMap +{ + // {{{ Properties + /** + * Description for var + * @var string + * @access public + */ + var $beginLevel = "
      "; + + /** + * Description for var + * @var string + * @access public + */ + var $endLevel = "
    "; + + /** + * Description for var + * @var string + * @access public + */ + var $beginItem = "
  • "; + + /** + * Description for var + * @var string + * @access public + */ + var $endItem = "
  • "; + + /** + * Description for var + * @var string + * @access public + */ + var $wholeThread; + + /** + * Description for var + * @var string + * @access public + */ + var $search = ""; + + /** + * Description for var + * @var unknown + * @access public + */ + var $DB; + // }}} + // {{{ __construct() + /** + * __construct + * + * Must be given a GLM_TEMPLATE object + * + * @param mixed $toolbox GLM_TEMPLATE Object + * + * @return void + * @access public + */ + function __construct(GLM_TEMPLATE $toolbox) + { + $this->toolbox =& $toolbox; + $this->DB =& $toolbox->DB; + } + // }}} + // {{{ sortChilds() + /** + * sortChilds + * + * Sort by Parent + * + * @param unknown $threads Array + * + * @return array Return array + * @access public + */ + function sortChilds($threads) + { + while (list($var, $value) = each($threads)) { + $childs[$value['parent']][$value['id']] = $value; + } + return $childs; + } + // }}} + // {{{ convertToThread() + /** + * convertToThread + * + * outputs the array with the correct styles and code applied + * + * @param unknown $threads Thread array + * @param unknown $thread Start with thread[0] will work it way down + * + * @return wholeThread + * @access public + **/ + function convertToThread($threads, $thread) + { + static $p,$level_counter; + if (!$level_counter) { + $level_counter = 1; + } + $this->wholeThread .= $this->beginLevel; + while (list($parent, $value) = each($thread)) { + $this->wholeThread .= $this->beginItem; + $page = $value['url']; + $this->wholeThread .= ''; + $this->wholeThread .= $value["category"] + . ""; + if ($threads[$parent]) { + ++$level_counter; + $this->convertToThread($threads, $threads[$parent]); + --$level_counter; + } + $this->wholeThread .= $this->endItem ."\n"; + } + $this->wholeThread .= $this->endLevel; + return $this->wholeThread; + } + // }}} +} +?> diff --git a/Toolkit/SortForm.php b/Toolkit/SortForm.php new file mode 100644 index 0000000..c5a1fc8 --- /dev/null +++ b/Toolkit/SortForm.php @@ -0,0 +1,67 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @version CVS: $Id: SortForm.php,v 1.6 2010/01/18 02:09:05 jamie Exp $ + * @link http://demo.gaslightmedia.com + */ + +/** + * Creates a sortform to be used w/ datagrid DataGrids + * + * @category HTML + * @package Toolkit_SortForm + * @author Jamie Kahgee + * @copyright 2008 Gaslight Media + * @license http://www.gaslightmedia.com Gaslightmedia + * @link http://demo.gaslightmedia.com + */ +class Toolkit_SortForm extends Toolkit_FormBuilder +{ + // {{{ properties + + /** + * The default rules to register for validating + * + * @var string + * @access protected + */ + protected $registeredRules = array(); + + // }}} + // {{{ toHTML() + + /** + * Render the form to a string + * + * Handle the rendering and validation of the form when displayed + * and submitted. + * + * @return string html form + * @access public + */ + public function toHTML() + { + $this->setupRenderers(); + if ($this->validate()) { + $output = parent::toHTML(); + } else if ($this->isSubmitted()) { + $output = $this->errorMsg; + $output .= parent::toHTML(); + } else { + $output = parent::toHTML(); + } + return $output; + } + + // }}} +} +?> diff --git a/Toolkit/Toolbox/Admin/EditPage.php b/Toolkit/Toolbox/Admin/EditPage.php new file mode 100644 index 0000000..f29a0f9 --- /dev/null +++ b/Toolkit/Toolbox/Admin/EditPage.php @@ -0,0 +1,1044 @@ + + * @release CVS: $Id: EditPage.php,v 1.16 2010/01/09 18:59:45 jamie Exp $: + * @license http://www.gaslightmedia.com Gaslightmedia + * @link http://demo.gaslightmedia.com + */ + +/** + * Edit Toolbox page + * + * Handles form to insert/edit a toolbox page + * + * @category Toolbox + * @package Toolkit_Toolbox + * @author Jamie Kahgee + * @copyright 2009 Jamie Kahgee + * @license http://www.gaslightmedia.com Gaslightmedia + * @link http://demo.gaslightmedia.com + */ +class Toolkit_Toolbox_Admin_EditPage + extends Toolkit_FormBuilder implements Toolkit_Form +{ + // {{{ properties + + /** + * Primary database table we need to interact with + * @var string + * @access protected + */ + public $tableName = 'bus_category'; + + /** + * How many levels deep do you want to show in the parent select list + * + * 0 = Show All Levels + * + * @var integer + * @access protected + */ + protected $maxDepth = 0; + + /** + * Don't need to register any rules for this form. + * @var array + * @access protected + */ + protected $registeredRules = array(); + + // }}} + // {{{ __construct() + + /** + * Class constructor + * + * Sets the database handler this class will use via the PDO passed in + * from the parameters. Sets up the flexyOptions from the default options + * defined in the setup.phtml file, updates where the templates directory + * and compiled templates directory are located. + * + * @param PDO $pdo PHP Data Object used to set the database + * handler + * @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->dbh = $pdo; + + $this->flexyOptions = $GLOBALS['flexyOptions']; + $this->flexyOptions['templateDir'] = TEMPLATES_DIR; + $this->flexyOptions['compileDir'] = COMPILED_DIR; + } + + // }}} + + // {{{ configureDefaults() + + /** + * Initializes default form values + * + * @return void + * @access public + */ + public function configureDefaults() + { + if (is_numeric($_GET['id'])) { + try { + $sql = " + SELECT * + FROM {$this->tableName} + WHERE id = :id"; + + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT); + $stmt->execute(); + $d = $stmt->fetch(); + $i = ''; + + $d['current_image'] = sprintf($i, THUMB . $d['image']); + + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } else { + $d = array( + 'template' => 1, + ); + } + $this->setupDefaults($d); + } + + // }}} + // {{{ configureElements() + + /** + * Form element definitions + * + * @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 + $pluralType = $c->getItem('section', 'listing type') + ->getItem('directive', 'plural') + ->getContent(); + + // Grouped Elements are defined here. + $submitBtns = array(); + + $submitBtns[] = array( + 'type' => 'submit', + 'req' => false, + 'name' => 'update_rmv', + 'display' => 'Update' + ); + $submitBtns[] = array( + 'type' => 'submit', + 'req' => false, + 'name' => 'cancel_rmv', + 'display' => 'Cancel' + ); + $submitBtns[] = array( + 'type' => 'submit', + 'req' => false, + 'name' => 'delete_rmv', + 'display' => 'Delete' + ); + + $templates = array(); + + $options = range(1, 6); + foreach ($options as $i) { + $img = ""; + + $templates[] = array( + 'type' => 'radio', + 'req' => false, + 'name' => 'template', + 'display' => "Template $i
    $img", + 'att' => $i, + 'opts' => $i, + ); + } + + // All Elements are created here. + // This includes group element definitions. + $res = $this->getConstant('MEMBERS_DB'); + $isErr = PEAR::isError($res); + if ($isErr) { + Toolkit_Common::handleError($e); + } + if ($res && !$isErr) { + $e[] = array( + 'type' => 'header', + 'req' => false, + 'name' => 'memberDbHdr', + 'display' => $pluralType, + ); + $e[] = array( + 'type' => 'static', + 'req' => false, + 'name' => 'pageCategories' + ); + // Note that we call to populate this select list at the + // bottom of this function after the element is made + // so we load attributes (classes) into each option as needed. + $e[] = array( + 'type' => 'select', + 'req' => false, + 'name' => 'memberCat', + 'display' => 'Member Categories', + 'opts' => array('' => '-- None --'), + 'att' => array( + 'multiple' => 'multiple', + 'size' => 7 + ) + ); + $e[] = array( + 'type' => 'advcheckbox', + 'req' => false, + 'name' => 'no_search_form', + 'display' => 'Search Box', + 'val' => array(0, 1) + ); + } + $e[] = array( + 'type' => 'header', + 'req' => false, + 'name' => 'pageAttributesHdr', + 'display' => 'Page Attributes' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'category', + 'display' => 'Navigation Name' + ); + $e[] = array( + 'type' => 'select', + 'req' => false, + 'name' => 'parent', + 'display' => 'Parent Page', + 'opts' => array('0' => '-- No Parent --'), + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'keyword', + 'display' => 'Keyword' + ); + $e[] = array( + 'type' => 'advcheckbox', + 'req' => false, + 'name' => 'section_links', + 'display' => 'Search', + 'opts' => 'Create a list of links to the paragraph headlines', + 'val' => array(0, 1) + ); + $res = $this->getConstant('HOME_HEADLINES'); + $isErr = PEAR::isError($res); + if ($isErr) { + Toolkit_Common::handleError($e); + } + if ($res && !$isErr) { + $e[] = array( + 'type' => 'header', + 'req' => false, + 'name' => 'homePageHeadlinesHdr', + 'display' => 'Headlines' + ); + $e[] = array( + 'type' => 'advcheckbox', + 'req' => false, + 'name' => 'featured', + 'display' => 'Home Page Headlines', + 'val' => array(0, 1) + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'feature_intro', + 'display' => 'Headline Intro' + ); + } + $e[] = array( + 'type' => 'header', + 'req' => false, + 'name' => 'pageBodyHdr', + 'display' => 'Page Body' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'intro', + 'display' => 'Page Title' + ); + $e[] = array( + 'type' => 'textarea', + 'req' => false, + 'name' => 'description', + 'display' => 'Description', + 'opts' => array( + 'cols' => 70, + 'rows' => 25 + ), + ); + if ($this->hasUploadedImage()) { + $e[] = array( + 'type' => 'static', + 'req' => false, + 'name' => 'current_image', + 'display' => 'Current Image' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'imagename', + 'display' => 'Image Caption' + ); + $e[] = array( + 'type' => 'checkbox', + 'req' => false, + 'name' => 'remove_image', + 'display' => 'Delete Image' + ); + } + $e[] = array( + 'type' => 'file', + 'req' => false, + 'name' => 'image', + 'display' => 'New Image' + ); + $e[] = array( + 'type' => 'group', + 'req' => false, + 'name' => 'page_layout', + 'group' => $templates, + 'label' => 'Template', + 'seperator' => '', + 'appendName' => false + ); + + // If we are editing a page, show three submit buttons + // otherwise, just show one insert button. + if (is_numeric($_GET['id'])) { + $e[] = array( + 'type' => 'group', + 'req' => false, + 'name' => 'submit_buttons', + 'group' => $submitBtns, + 'label' => '', + 'seperator' => '', + 'appendName' => false, + ); + } else { + $e[] = array( + 'type' => 'submit', + 'req' => false, + 'name' => 'insert_rmv', + 'display' => 'Insert' + ); + } + + $this->setupElements($e); + // Load the member categories after the elements have been created + // so we can get more control how the options are rendered + // ie (adding classes to them) + $res = $this->getConstant('MEMBERS_DB'); + $isErr = PEAR::isError($res); + if ($isErr) { + Toolkit_Common::handleError($e); + } + if ($res && !$isErr) { + $this->loadMemberCategories(); + } + // Do the same for the pages + $this->loadParentPages(); + } + + // }}} + // {{{ 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() + + /** + * Bundle all form configuration calls into one function call + * + * @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(); + } + + // }}} + // {{{ configureRules() + + /** + * Form rule definitions + * + * Adds validation rules for the given fields + * + * @return void + * @access public + */ + public function configureRules() + { + $r = array(); + // Form Rules + + $this->setupRules($r); + } + + // }}} + + // {{{ getCurrentParent() + + /** + * Gets the parent id of a page + * + * @param integer $id page id + * + * @return integer parent id + * @access protected + */ + protected function getCurrentParent($id) + { + try { + $sql = " + SELECT parent + FROM {$this->tableName} + WHERE id = :id"; + + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(':id', $id, PDO::PARAM_INT); + $stmt->execute(); + $stmt->bindColumn('parent', $parent); + $stmt->fetch(); + + return $parent; + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + // {{{ getNewParentPosition() + + /** + * Gets the position to use for a page + * + * If we are inserting a new page we need to get the position to insert + * the new page at. Or if we are updating an existing page and reassigning + * it to a new parent, we need to get the new position to insert + * the page at. + * + * @param integer $parent page id of the new parent page + * + * @return integer new position to use + * @access protected + */ + protected function getNewParentPosition($parent) + { + try { + $sql = " + SELECT count(*) + 1 AS newparent + FROM {$this->tableName} + WHERE parent = :parent + AND id != :home_id"; + + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(':parent', $parent, PDO::PARAM_INT); + $stmt->bindValue(':home_id', HOME_ID, PDO::PARAM_INT); + $stmt->execute(); + $stmt->bindColumn('newparent', $newParent); + $stmt->fetch(); + + if ($parent == 0) { + ++$newParent; + } + + return $newParent; + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + // {{{ getTableName() + + /** + * Gets the primary table name + * + * @return string table name + * @access public + */ + public function getTableName() + { + return $this->tableName; + } + + // }}} + // {{{ getConstant() + + /** + * fetch a defined constant value + * + * @param string $constant constant name + * + * @return mixed constant value + * @acess protected + */ + protected function getConstant($constant) + { + if (!defined($constant)) { + return PEAR::raiseError('calling undefined constant'); + } else { + return constant($constant); + } + } + + // }}} + + // {{{ hasUploadedImage() + + /** + * Check to see if page we are editing has an uploaded image + * + * @return boolean If page has a previously uploaded image + * @access protected + */ + protected function hasUploadedImage() + { + if (!is_numeric($_GET['id'])) { + return false; + } + try { + $sql = " + SELECT * + FROM {$this->tableName} + WHERE id = :id"; + + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT); + $stmt->execute(); + $stmt->bindColumn('image', $image); + $row = $stmt->fetch(); + return !is_null($image); + //return !(is_null($image) || empty($image)); + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + + // {{{ loadMemberCategories() + + /** + * Loads member categories into the select list + * + * Gets an array structure of the member categories in a linear tree order + * Then walk through the array and load each category into the select list + * + * @return void + * @access public + */ + public function loadMemberCategories() + { + try { + // Get a tree list of categories in linear order with + // category keys in the values and their level in the tree + // in the value + $c = Toolkit_Common::getHierarchicalTreeStructure( + $this->dbh, + 'category', + 'category_id', + 'parent_id' + ); + + // Get all the data about each category + $sql = " + SELECT * + FROM category + WHERE category_id = ?"; + + $stmt = $this->dbh->prepare($sql); + // Get the member categories select list element + $e =& $this->getElement('memberCat'); + foreach ($c as $i => $j) { + $stmt->execute(array($i)); + $row = $stmt->fetch(); + // the class level is always 1 less than what is reported + // from our $c array + $x = $j - 1; + // Add the option data to the select list. + $e->addOption($row['name'], $i, array('class' => "level-$x")); + } + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + // {{{ loadParentPages() + + /** + * Load option elements into the parent select list + * + * These options are loaded via this seperate function vs inline w/ the + * element definition b/c we need a little more control defining + * the class names for each option so they will render nice when a user + * is looking at the list. + * + * @return void + * @throws PDOException throws exception on sql error + * @access public + */ + public function loadParentPages() + { + try { + // Get a tree list of categories in linear order with + // category keys in the values and their level in the tree + // in the value + $c = Toolkit_Common::getHierarchicalTreeStructure( + $this->dbh, + 'bus_category', + 'id', + 'parent', + 'pos', + 0, + $this->maxDepth + ); + + // unset the home page, this is never an option to have children + // underneath it. + unset($c[HOME_ID]); + + // If we are editing a page, then we don't want that page + // to show up as an option in the select list. + if (is_numeric($_GET['id'])) { + reset($c); + // Get us to the point in the array were this page is located + while (key($c) != $_GET['id'] && current($c) !== false) { + next($c); + } + // Make sure we didn't traverse off the end of the array + if (current($c) !== false) { + // get the starting level we are currently at + $sl = current($c); + // remove this page (the one we're editing) from the + // array and advance the internal array pointer + unset($c[key($c)]); + // now we need to make sure all sub pages beneath this + // page are also not being shown + + // while we don't traverse off the end of the array + while (current($c) !== false) { + // get the current sub level we are at + $csl = current($c); + // if the current sub-level is the same as the + // starting level, that means we have traversed through + // all the sub-pages and can break out of the loop + if ($csl == $sl) { + break; + } else { + // we are still in a sub-level page, so unset + // this page so it doesn't show, and advance + // the internal array pointer + unset($c[key($c)]); + } + } + } + } + + // Get all the data about each category + $sql = " + SELECT * + FROM bus_category + WHERE id = ?"; + + $stmt = $this->dbh->prepare($sql); + // Get the member categories select list element + $e =& $this->getElement('parent'); + foreach ($c as $i => $j) { + $stmt->execute(array($i)); + $row = $stmt->fetch(); + // the class level is always 1 less than what is reported + // from our $c array + $x = $j - 1; + // Add the option data to the select list. + $e->addOption($row['category'], $i, array('class' => "level-$x")); + } + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + + // {{{ insertPage() + + /** + * Create a new page in the site by inserting values into the DB + * + * @param array $values Submitted form values + * + * @return boolean Result of insertion + * @access protected + */ + protected function insertPage($values) + { + // Get the member categories if they exists so we don't try and + // insert them into the wrong table. + $memberCats = $values['memberCat']; + unset($values['memberCat']); + + // Get the value of the new position this page will be set to. + $values['pos'] = $this->getNewParentPosition($values['parent']); + + // a non empty file size indicates to use an image has been uploaded. + if (!empty($values['image']['size'])) { + $values['image'] = $this->uploadImage('image'); + if ($values['image'] === false) { + return PEAR::raiseError('Invalid image response'); + } + } else { + unset($values['image']); + } + + $sql = Toolkit_Common::createSQLInsert( + $this->tableName, + array_keys($values) + ); + + try { + $this->dbh->beginTransaction(); + Toolkit_Common::processQuery( + $this->dbh, + $this->tableName, + $sql, + $values + ); + + // If we are trying to associate member categories + // with the toolbox page then insert them here. + if (is_array($memberCats) && !empty($memberCats)) { + // Need to get the last id inserted into the table. + $sql = " + SELECT id + FROM {$this->tableName} + ORDER BY id DESC + LIMIT 1"; + + $row = $this->dbh->query($sql)->fetch(); + $sql = Toolkit_Common::createSQLInsert( + 'bus_cat_member', + array('catid', 'memb_type') + ); + + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(':catid', $row['id'], PDO::PARAM_INT); + // zip through all the member categories selected + // and insert them into the table. + foreach ($memberCats as $i) { + if (is_numeric($i)) { + $stmt->bindParam(':memb_type', $i, PDO::PARAM_INT); + $stmt->execute(); + } + } + } + + return $this->dbh->commit(); + } catch (PDOException $e) { + $this->dbh->rollback(); + return Toolkit_Common::handleError($e); + } + } + + // }}} + + // {{{ 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']) ? 'updatePage' : 'insertPage'; + return $this->$function($values); + } + + // }}} + + // {{{ removeImage() + // @codeCoverageIgnoreStart + + /** + * Deletes an image from the file server + * + * @param string $fileName Name of the image to delete + * + * @return void + * @access protected + */ + protected function removeImage($fileName) + { + $is = new Toolkit_Image_Server(); + $is->imageDelete($fileName); + } + + // @codeCoverageIgnoreEnd + // }}} + + // {{{ setMaxDepth() + + /** + * Sets the max depth level that the parent page select list will show + * + * @param integer $md New max depth + * + * @return void + * @access public + */ + public function setMaxDepth($md) + { + $this->maxDepth = $md; + } + + // }}} + // {{{ 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("\n\t\n\t\t$required{label}$error{element}\n\t", 'submit_buttons'); + $renderer->setElementTemplate("\n\t\n\t\t$required{label}$error{element}\n\t", 'insert_rmv'); + + $renderer->setGroupTemplate("\n\t\n\t\t\n\t\t\t{content}\n\t\t\n\t
    ", 'page_layout'); + $renderer->setGroupElementTemplate("\n\t\n\t\t\n\t", 'page_layout'); + } + + // }}} + + // {{{ toHtml() + + /** + * Handles how to display the current step the user is at in the form + * + * @return string rendered html form + * @access public + */ + public function toHtml() + { + $validated = $this->validate(); + $this->setupRenderers(); + if ($validated) { + $this->cleanForm(); + + $r = $this->process( + array(&$this, 'processData'), + $this->mergeFiles + ); + if (PEAR::isError($r)) { + return Toolkit_Common::handleError($r); + } else { + $this->freeze(); + $output = $this->successMsg; + } + } elseif ($this->isSubmitted()) { + $output = $this->errorMsg; + $output .= parent::toHTML(); + } else { + $output = parent::toHTML(); + } + return $output; + } + + // }}} + + // {{{ updatePage() + + /** + * Update an existing page in the site by updating values in the DB + * + * @param array $values Submitted form values + * + * @return boolean Result of insertion + * @access protected + */ + protected function updatePage($values) + { + // Make sure we are dealing w/ a valid page + if (!is_numeric($_GET['id'])) { + return PEAR::raiseError('Invalid page id'); + } + + // Handle user deleting the page image. + if (array_key_exists('remove_image', $values)) { + $this->removeImage($values['imagename']); + + // unset value so its not included in the update sql query + unset($values['remove_image']); + // set image and imagename to null to overwrite value in db. + // if we are not uploading a new image. + if (empty($values['image']['size'])) { + $values['image'] = $values['imagename'] = null; + } + } + + // a non empty file size indicates to use an image has been uploaded. + if (!empty($values['image']['size'])) { + $values['image'] = $is->imageUpload('image'); + if ($values['image'] === false) { + return PEAR::raiseError('Invalid image response'); + } + } elseif (!is_null($values['image'])) { + unset($values['image']); + } + + // Get the parent id this page is currently set to in the DB. + $curPar = $this->getCurrentParent($_GET['id']); + // parents will be different if we are reassining to a new parent + if ($curPar != $values['parent']) { + // Get an updated position for the new parent page. + $values['pos'] = $this->getNewParentPosition($values['parent']); + } + + try { + $sql = Toolkit_Common::createSQLUpdate( + $this->tableName, + array_keys($values), + array('id = :id') + ); + + $values['id'] = $_GET['id']; + return Toolkit_Common::processQuery( + $this->dbh, + $this->tableName, + $sql, + $values + ); + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + // {{{ uploadImage() + // @codeCoverageIgnoreStart + + /** + * Uploads an image to the image server + * + * @param string $key name of the file upload key to find the image in the + * $_FILES array + * + * @return mixed file name on success, false on error + * @access protected + */ + protected function uploadImage($key) + { + $is = new Toolkit_Image_Server(); + return $is->imageUpload($key); + } + + // @codeCoverageIgnoreEnd + // }}} +} +?> diff --git a/Toolkit/Toolbox/Admin/EditParagraph.php b/Toolkit/Toolbox/Admin/EditParagraph.php new file mode 100644 index 0000000..b6e3d79 --- /dev/null +++ b/Toolkit/Toolbox/Admin/EditParagraph.php @@ -0,0 +1,692 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @version CVS: $Id: EditParagraph.php,v 1.4 2009/10/27 14:46:32 jamie Exp $ + * @link http://demo.gaslightmedia.com + */ + +/** + * Short description for class + * + * Long description (if any) ... + * + * @category CategoryName + * @package Toolkit_Toolbox + * @author Jamie Kahgee + * @copyright 2009 Jamie Kahgee + * @license http://www.gaslightmedia.com Gaslightmedia + * @link http://demo.gaslightmedia.com + */ +class Toolkit_Toolbox_Admin_EditParagraph extends Toolkit_FormBuilder +{ + // {{{ properties + + + /** + * Description for protected + * @var string + * @access protected + */ + protected $tableName = 'bus'; + + // }}} + // {{{ __construct() + + /** + * Class constructor + * + * @param string $formName Form's name. + * @param PDO $pdo PHP Data Object used for DB calls + * @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, + PDO $pdo, + $method = 'post', + $action = '', + $target = '', + $attributes = null, + $trackSubmit = false + ) { + parent::__construct( + $formName, + $method, + $action, + $target, + $attributes, + $trackSubmit + ); + $this->dbh = $pdo; + $this->flexyOptions = $GLOBALS['flexyOptions']; + $this->flexyOptions['templateDir'] = TEMPLATES_DIR; + $this->flexyOptions['compileDir'] = COMPILED_DIR; + } + + // }}} + + // {{{ createTables() + + /** + * Read file from parameter and use the PDO parameter to create process file + * + * @param object $pdo Database handler + * @param string $file full path of file to parse + * + * @return void + * @access public + * @static + */ + static public function createTables(PDO $pdo, $file) + { + $sql = file_get_contents($file); + $tok = strtok($sql, ';'); + while ($tok !== false) { + $pdo->query($tok); + $tok = strtok(';'); + } + } + + // }}} + // {{{ configureDefaults() + + /** + * Initializes default form values + * + * @return void + * @access public + */ + public function configureDefaults() + { + if (is_numeric($_GET['id'])) { + try { + $sql = " + SELECT * + FROM {$this->tableName} + WHERE id = :id"; + + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT); + $stmt->execute(); + $d = $stmt->fetch(); + $i = ''; + + $d['current_image'] = sprintf($i, THUMB . $d['image']); + + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } else { + $d = array( + 'template' => 1, + ); + } + $this->setupDefaults($d); + } + + // }}} + // {{{ configureElements() + + /** + * Form element definitions + * + * @return void + * @access public + */ + public function configureElements() + { + $e = array(); + // Grouped Elements are defined here. + $submitBtns = array(); + + $submitBtns[] = array( + 'type' => 'submit', + 'req' => false, + 'name' => 'update_rmv', + 'display' => 'Update' + ); + $submitBtns[] = array( + 'type' => 'submit', + 'req' => false, + 'name' => 'cancel_rmv', + 'display' => 'Cancel' + ); + $submitBtns[] = array( + 'type' => 'submit', + 'req' => false, + 'name' => 'delete_rmv', + 'display' => 'Delete' + ); + + // All Elements are created here. + // This includes group element definitions. + $e[] = array( + 'type' => 'header', + 'req' => false, + 'name' => 'paragraphAttributesHdr', + 'display' => 'Paragraph Attributes' + ); + $e[] = array( + 'type' => 'select', + 'req' => false, + 'name' => 'page', + 'display' => 'Page', + 'opts' => array(), + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'intro', + 'display' => 'Paragraph Title' + ); + $e[] = array( + 'type' => 'textarea', + 'req' => false, + 'name' => 'description', + 'display' => 'Description', + 'opts' => array( + 'cols' => 70, + 'rows' => 25 + ), + ); + if ($this->hasUploadedImage()) { + $e[] = array( + 'type' => 'static', + 'req' => false, + 'name' => 'current_image', + 'display' => 'Current Image' + ); + $e[] = array( + 'type' => 'text', + 'req' => false, + 'name' => 'imagename', + 'display' => 'Image Caption' + ); + $e[] = array( + 'type' => 'checkbox', + 'req' => false, + 'name' => 'remove_image', + 'display' => 'Delete Image' + ); + } + $e[] = array( + 'type' => 'file', + 'req' => false, + 'name' => 'image', + 'display' => 'New Image' + ); + + // If we are editing a page, show three submit buttons + // otherwise, just show one insert button. + if (is_numeric($_GET['id'])) { + $e[] = array( + 'type' => 'group', + 'req' => false, + 'name' => 'submit_buttons', + 'group' => $submitBtns, + 'label' => '', + 'seperator' => '', + 'appendName' => false, + ); + } else { + $e[] = array( + 'type' => 'submit', + 'req' => false, + 'name' => 'insert_rmv', + 'display' => 'Insert' + ); + } + + $this->setupElements($e); + // Do the same for the pages + $this->loadParagraphPages(); + } + + // }}} + // {{{ 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() + + /** + * Bundle all form configuration calls into one function call + * + * @return void + * @access public + */ + public function configureForm() + { + $this->configureElements(); + $this->configureRules(); + $this->configureFilters(); + $this->configureDefaults(); + } + + // }}} + // {{{ configureRules() + + /** + * Form rule definitions + * + * Adds validation rules for the given fields + * + * @return void + * @access public + */ + public function configureRules() + { + $r = array(); + // Form Rules + + $this->setupRules($r); + } + + // }}} + // {{{ getTableName() + + + /** + * Short description for function + * + * Long description (if any) ... + * + * @return string Return description (if any) ... + * @access public + */ + public function getTableName() + { + return $this->tableName; + } + + // }}} + + // {{{ hasUploadedImage() + + /** + * Check to see if page we are editing has an uploaded image + * + * @return boolean If page has a previously uploaded image + * @access protected + */ + protected function hasUploadedImage() + { + if (!is_numeric($_GET['id'])) { + return false; + } + try { + $sql = " + SELECT * + FROM {$this->tableName} + WHERE id = :id"; + + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT); + $stmt->execute(); + $stmt->bindColumn('image', $image); + $row = $stmt->fetch(); + return !is_null($image); + //return !(is_null($image) || empty($image)); + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + + // {{{ loadParagraphPages() + + /** + * Load option elements into the parent select list + * + * These options are loaded via this seperate function vs inline w/ the + * element definition b/c we need a little more control defining + * the class names for each option so they will render nice when a user + * is looking at the list. + * + * @return void + * @throws PDOException throws exception on sql error + * @access public + */ + public function loadParagraphPages() + { + try { + // Get a tree list of categories in linear order with + // category keys in the values and their level in the tree + // in the value + $c = Toolkit_Common::getHierarchicalTreeStructure( + $this->dbh, + 'bus_category', + 'id', + 'parent', + 'pos', + 1, + $this->maxDepth + ); + + // Get all the data about each category + $sql = " + SELECT * + FROM bus_category + WHERE id = ?"; + + $stmt = $this->dbh->prepare($sql); + // Get the member categories select list element + $e =& $this->getElement('page'); + foreach ($c as $i => $j) { + $stmt->execute(array($i)); + $row = $stmt->fetch(); + // the class level is always 1 less than what is reported + // from our $c array + $x = $j - 1; + // Add the option data to the select list. + $e->addOption($row['category'], $i, array('class' => "level-$x")); + } + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + + // {{{ insertPage() + + /** + * Create a new page in the site by inserting values into the DB + * + * @param array $values Submitted form values + * + * @return boolean Result of insertion + * @access protected + */ + protected function insertPage($values) + { + // Get the member categories if they exists so we don't try and + // insert them into the wrong table. + $memberCats = $values['memberCat']; + unset($values['memberCat']); + + // Get the value of the new position this page will be set to. + $values['pos'] = $this->getNewParentPosition($values['parent']); + + // a non empty file size indicates to use an image has been uploaded. + if (!empty($values['image']['size'])) { + $values['image'] = $this->uploadImage('image'); + if ($values['image'] === false) { + return PEAR::raiseError('Invalid image response'); + } + } else { + unset($values['image']); + } + + $sql = Toolkit_Common::createSQLInsert( + $this->tableName, + array_keys($values) + ); + + try { + $this->dbh->beginTransaction(); + Toolkit_Common::processQuery( + $this->dbh, + $this->tableName, + $sql, + $values + ); + + // If we are trying to associate member categories + // with the toolbox page then insert them here. + if (is_array($memberCats) && !empty($memberCats)) { + // Need to get the last id inserted into the table. + $sql = " + SELECT id + FROM {$this->tableName} + ORDER BY id DESC + LIMIT 1"; + + $row = $this->dbh->query($sql)->fetch(); + $sql = Toolkit_Common::createSQLInsert( + 'bus_cat_member', + array('catid', 'memb_type') + ); + + $stmt = $this->dbh->prepare($sql); + $stmt->bindParam(':catid', $row['id'], PDO::PARAM_INT); + // zip through all the member categories selected + // and insert them into the table. + foreach ($memberCats as $i) { + if (is_numeric($i)) { + $stmt->bindParam(':memb_type', $i, PDO::PARAM_INT); + $stmt->execute(); + } + } + } + + return $this->dbh->commit(); + } catch (PDOException $e) { + $this->dbh->rollback(); + return Toolkit_Common::handleError($e); + } + } + + // }}} + + // {{{ 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']) ? 'updatePage' : 'insertPage'; + return $this->$function($values); + } + + // }}} + // {{{ removeImage() + // @codeCoverageIgnoreStart + + /** + * Deletes an image from the file server + * + * @param string $fileName Name of the image to delete + * + * @return void + * @access protected + */ + protected function removeImage($fileName) + { + $is = new Toolkit_Image_Server(); + $is->imageDelete($fileName); + } + + // @codeCoverageIgnoreEnd + // }}} + + // {{{ setMaxDepth() + + /** + * Sets the max depth level that the parent page select list will show + * + * @param integer $md New max depth + * + * @return void + * @access public + */ + public function setMaxDepth($md) + { + $this->maxDepth = $md; + } + + // }}} + // {{{ 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("\n\t\n\t\t$required{label}$error{element}\n\t", 'submit_buttons'); + $renderer->setElementTemplate("\n\t\n\t\t$required{label}$error{element}\n\t", 'insert_rmv'); + + $renderer->setGroupTemplate("\n\t\n\t\t\n\t\t\t{content}\n\t\t\n\t
    ", 'page_layout'); + $renderer->setGroupElementTemplate("\n\t\n\t\t\n\t", 'page_layout'); + } + + // }}} + + // {{{ updatePage() + + /** + * Update an existing page in the site by updating values in the DB + * + * @param array $values Submitted form values + * + * @return boolean Result of insertion + * @access protected + */ + protected function updatePage($values) + { + // Make sure we are dealing w/ a valid page + if (!is_numeric($_GET['id'])) { + return PEAR::raiseError('Invalid page id'); + } + + // Handle user deleting the page image. + if (array_key_exists('remove_image', $values)) { + $this->removeImage($values['imagename']); + + // unset value so its not included in the update sql query + unset($values['remove_image']); + // set image and imagename to null to overwrite value in db. + // if we are not uploading a new image. + if (empty($values['image']['size'])) { + $values['image'] = $values['imagename'] = null; + } + } + + // a non empty file size indicates to use an image has been uploaded. + if (!empty($values['image']['size'])) { + $values['image'] = $is->imageUpload('image'); + if ($values['image'] === false) { + return PEAR::raiseError('Invalid image response'); + } + } elseif (!is_null($values['image'])) { + unset($values['image']); + } + + // Get the parent id this page is currently set to in the DB. + $curPar = $this->getCurrentParent($_GET['id']); + // parents will be different if we are reassining to a new parent + if ($curPar != $values['parent']) { + // Get an updated position for the new parent page. + $values['pos'] = $this->getNewParentPosition($values['parent']); + } + + try { + $sql = Toolkit_Common::createSQLUpdate( + $this->tableName, + array_keys($values), + array('id = :id') + ); + + $values['id'] = $_GET['id']; + return Toolkit_Common::processQuery( + $this->dbh, + $this->tableName, + $sql, + $values + ); + } catch (PDOException $e) { + return Toolkit_Common::handleError($e); + } + } + + // }}} + // {{{ uploadImage() + // @codeCoverageIgnoreStart + + /** + * Uploads an image to the image server + * + * @param string $key name of the file upload key to find the image in the + * $_FILES array + * + * @return mixed file name on success, false on error + * @access protected + */ + protected function uploadImage($key) + { + $is = new Toolkit_Image_Server(); + return $is->imageUpload($key); + } + + // @codeCoverageIgnoreEnd + // }}} +} +?> diff --git a/Toolkit/Toolbox/Admin/toolbox.sql b/Toolkit/Toolbox/Admin/toolbox.sql new file mode 100644 index 0000000..5fc4cdb --- /dev/null +++ b/Toolkit/Toolbox/Admin/toolbox.sql @@ -0,0 +1,33 @@ +CREATE TABLE bus_category ( +id SERIAL PRIMARY KEY, +parent INTEGER, +category TEXT, +intro TEXT, +description TEXT, +image TEXT, +imagename TEXT, +active BOOLEAN DEFAULT FALSE, +pos INTEGER, +keyword TEXT, +template INTEGER, +featured BOOLEAN DEFAULT FALSE, +no_search_form BOOLEAN DEFAULT FALSE, +feature_intro TEXT, +section_links BOOLEAN DEFAULT FALSE +); + +CREATE TABLE bus ( +id SERIAL PRIMARY KEY, +name TEXT, +description TEXT, +image TEXT, +imagename TEXT, +back_to_top BOOLEAN DEFAULT FALSE +); + +CREATE TABLE bus_category_bus ( +id SERIAL PRIMARY KEY, +busid INTEGER, +catid INTEGER, +pos INTEGER +); diff --git a/Toolkit/Toolbox/assets/.keepme b/Toolkit/Toolbox/assets/.keepme new file mode 100644 index 0000000..e69de29 diff --git a/Toolkit/Tree.php b/Toolkit/Tree.php new file mode 100644 index 0000000..5af1553 --- /dev/null +++ b/Toolkit/Tree.php @@ -0,0 +1,145 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @release CVS: $Id: Tree.php,v 1.4 2009/06/18 14:12:50 jamie Exp $ + * @link http://demo.gaslightmedia.com + */ + +/** + * Create tree structures of database entries + * + * Base class used to setup tree objects that will render + * database structures into iterable PHP objects. + * + * @category Toolkit + * @package Toolkit_Tree + * @author Jamie Kahgee + * @copyright 2008 Gaslight Media + * @license http://www.gaslightmedia.com Gaslightmedia + * @link http://demo.gaslightmedia.com + */ +abstract class Toolkit_Tree +{ + // {{{ properties + + /** + * Database ID of tuple + * + * @var int + * @access public + */ + public $catid = 0; + + /** + * Name of object + * + * @var string + * @access public + */ + public $category; + + /** + * Children of object + * + * @var array + * @access public + */ + public $children = array(); + + /** + * Parent of this category + * + * @var array + * @access public + */ + public $parentId; + + /** + * Database connection handle + * + * @var PDO Object + * @access protected + */ + protected $dbh; + + // }}} + // {{{ __construct() + + /** + * Setup the objects properties and call to setup children + * + * @param integer $catid ID of the Database object + * @param string $name Name of the Database object + * @param PDO $dbh Database handler object + * @param integer $parentId Id of parent node + * + * @author Jamie Kahgee + * @access public + */ + public function __construct($catid, $name, PDO $dbh, $parentId = 0) + { + $this->parentId = $parentId; + $this->catid = $catid; + $this->category = $name; + $this->dbh = $dbh; + $this->addChildren(); + } + + // }}} + // {{{ __get() + + /** + * utilized for reading data from inaccessible members + * + * @param string $name property name + * + * @return mixed void + * @access public + */ + public function __get($name) + { + return $this->$name; + } + + // }}} + // {{{ __set() + + + /** + * Run when writing data to inaccessible members + * + * @param string $name property + * @param string $value new value + * + * @return void + * @access public + */ + public function __set($name, $value) + { + $this->$name = $value; + } + + // }}} + // {{{ addChildren() + + /** + * Attaches children to tree object + * + * @author Jamie Kahgee + * @return void + * @access protected + */ + abstract protected function addChildren(); + + // }}} +} +?> diff --git a/Toolkit/Weather.php b/Toolkit/Weather.php new file mode 100755 index 0000000..60a9d09 --- /dev/null +++ b/Toolkit/Weather.php @@ -0,0 +1,203 @@ + + * @copyright 2008 Gaslight Media + * @license http://www.gaslightmedia.com/license.txt The Gaslight License + * @version CVS: $Id: Weather.php,v 1.6 2009/09/16 11:20:51 jamie Exp $ + * @link <> + */ + +/** + * Weather class for Gaslight Media + * + * You can get the stationId for weather at + * http://www.weather.gov/xml/current_obs/seek.php?state=mi + * Uses NOAA for getting the rss feed for weather + * + * @category Toolkit + * @package Toolkit_Weather + * @author Steve Sutton + * @copyright 2008 Gaslight Media + * @license http://www.gaslightmedia.com/license.txt The Gaslight License + * @link <> + */ +class Toolkit_Weather +{ + //{{{ __Class Properties + + + /** + * The xml file used for caching the feed + * @var $_weatherFile string + * @access private + */ + private $_weatherFile; + + /** + * Station identifier for the feed + * @link http://www.weather.gov/xml/current_obs/seek.php?state=mi + * + * @var $_stationId string + * @access private + */ + private $_stationId = 'KPLN'; + + + /** + * XMLReader object for parsing feed + * @var $_xml object + * @access private + */ + private $_xml; + + /** + * Description for private + * @var $_assoc array + * @access private + */ + private $_assoc; + + /** + * Storage array for the current conditions + * @var $currendCond array + * @access public + */ + public $currentCond; + + /** + * Boolean if the file exists or not + * @var $_cacheFileExist boolean + * @access private + */ + private $_cacheFileExist = false; + + //}}} + //{{{ __construct() + + /** + * Class Constructer + * + * @return void + * @access public + */ + function __construct() + { + $currentErrorMask = ini_get('error_reporting'); + error_reporting(0); + $this->_weatherFile = BASE.'weather-feed.xml'; + $this->interval = 25; // interval in minutes for page cache + $this->fetchWeather(); + $this->setCurrentCond(); + error_reporting($currentErrorMask); + } + + //}}} + //{{{ fetchWeather() + + + /** + * fetchWeather + * + * THis will use curl to grab the weather feed using + * the $_weatherFile as destination + * and the $_stationId for the xml file name + * + * @return void + * @access public + */ + function fetchWeather() + { + if (is_file($this->_weatherFile)) { + $time2hoursago = mktime( + date('H'), + date('i') - $this->interval, + date('s'), + date('m'), + date('d'), + date('Y') + ); + $file_time = filemtime($this->_weatherFile); + if ($file_time < $time2hoursago) { + $this->grabFeedUrl(); + } + if (is_file($this->_weatherFile)) { + $this->_cacheFileExist = true; + } + } else { + $this->grabFeedUrl(); + if (is_file($this->_weatherFile)) { + $this->_cacheFileExist = true; + } + } + } + + //}}} + // {{{ grabFeedUrl() + + + /** + * grabFeedUrl + * + * @return void + * @access public + */ + function grabFeedUrl() + { + // the NOAA xml feed url to be used + // from the _stationId + $feed_url = 'http://www.weather.gov/xml/current_obs/' + .$this->_stationId.'.xml'; + // Curl Options used for connection + $curlOptions = array( + CURLOPT_URL => $feed_url, + CURLOPT_HEADER => 0, + CURLOPT_RETURNTRANSFER => 1, + CURLOPT_TIMEOUT => 15, + CURLOPT_CONNECTTIMEOUT => 5, + CURLOPT_FAILONERROR => 1, + ); + // start curl object + $ch = curl_init(); + // set options + curl_setopt_array($ch, $curlOptions); + // assign the response to a string variable + $response = curl_exec($ch); + // grab the connection info to check for http_code = 200 + $info = curl_getinfo($ch); + curl_close($ch); + if ($info['http_code'] == '200') { + file_put_contents($this->_weatherFile, $response); + } else { + @touch($this->_weatherFile); + } + } + + + // }}} + //{{{ setCurrentCond() + + /** + * Set currentCond + * + * Set the currentCond clas var up with variables from the xml file + * from the weather feed + * + * @return void + * @access public + */ + function setCurrentCond() + { + $xml = new XML_Unserializer(); + $xml->unserialize($this->_weatherFile, true); + $this->currentCond = $xml->getUnserializedData(); + } + + //}}} +} +?> diff --git a/Toolkit/qfcaptcha.php b/Toolkit/qfcaptcha.php new file mode 100755 index 0000000..f4bf079 --- /dev/null +++ b/Toolkit/qfcaptcha.php @@ -0,0 +1,39 @@ + + * @copyright 2006-2008 by Philippe Jausions / 11abacus + * @license http://www.opensource.org/licenses/bsd-license.php New BSD + * @version CVS: $Id: qfcaptcha.php,v 1.2 2009/10/01 16:00:02 jamie Exp $ + * @filesource + * @link http://pear.php.net/package/HTML_QuickForm_CAPTCHA + * @see qfcaptcha_form_image.php + * @see qfcaptcha_form_random.php + */ + +// Require the class before opening the session +// so the instance unserialize properly +require_once '../setup.phtml'; +require_once 'Text/CAPTCHA.php'; +require_once 'Text/CAPTCHA/Driver/Image.php'; + +HTTP_Session2::useCookies(false); +HTTP_Session2::start(); + +header('Content-Type: image/jpeg'); + +$sessionVar = (empty($_REQUEST['var'])) + ? '_HTML_QuickForm_CAPTCHA' + : $_REQUEST['var']; + +// Force a new CAPTCHA for each one displayed +$_SESSION[$sessionVar]->setPhrase(); + +echo $_SESSION[$sessionVar]->getCAPTCHAAsJPEG(); +?> diff --git a/admin/.htaccess b/admin/.htaccess new file mode 100644 index 0000000..38dcd05 --- /dev/null +++ b/admin/.htaccess @@ -0,0 +1 @@ +RewriteEngine Off diff --git a/admin/Photos/edit-default.php b/admin/Photos/edit-default.php new file mode 100644 index 0000000..44d2417 --- /dev/null +++ b/admin/Photos/edit-default.php @@ -0,0 +1,35 @@ +db_exec($query)) { + die('error updating'); + } else { + echo '

    Updated

    '; + } +} +$query = "select * from photo_default where id = 1;"; +echo ' + + +'; +if ($res = $DB->db_exec($query)) { + $obj = pg_fetch_object($res, 0, PGSQL_ASSOC); + echo ' + + + '; + echo ' + + + '; + echo ' + + '; +} +?> +
    Header:
    Text:
    + + diff --git a/admin/Photos/edit_display.phtml b/admin/Photos/edit_display.phtml new file mode 100644 index 0000000..ee77926 --- /dev/null +++ b/admin/Photos/edit_display.phtml @@ -0,0 +1,20 @@ +'; +echo ''; +echo ''; +echo ''; +echo ''; +echo ''; +echo ''; +echo ''; +echo ''; +echo '
    Category:'.parent_select( $catid ).'
    '; +echo ''; +footer(); +?> diff --git a/admin/Photos/edit_photo.phtml b/admin/Photos/edit_photo.phtml new file mode 100644 index 0000000..6f61e33 --- /dev/null +++ b/admin/Photos/edit_photo.phtml @@ -0,0 +1,139 @@ + "edit_photo.phtml?catid=$catid", + "List Photos" => "list_photo.phtml?catid=$catid" + ); +GLM_TOOLBOX::html_nav_table($lnav, 2); +if (isset($id)) { + $qs = "select id,title,catid,description,image,pos from photo where id = $id"; + if (!$res = $DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG, 1); + } + $row = $DB->db_fetch_array($res, $i, PGSQL_ASSOC); + if (!$row['id']) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG, 0); + } +} else { + $row = array( + 'title' => '', + 'catid' => $catid, + 'description' => '', + 'image' => ''); +} +function catid_select($catid) +{ + $DB =& $GLOBALS['DB']; + $qs = " + SELECT id, category + FROM photo_category"; + if (!$res2 = $DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG, 0); + } + $select = '"; + break; + + case "pos": + echo ""; + break; + + case "title": + echo "Photo Name:"; + GLM_TOOLBOX::text_box("title",$value); + echo ""; + break; + + case "catid": + echo " + + Album Name"; + $output = catid_select($value); + echo "".$output.""; + echo ""; + break; + + case "description": + echo "Description + "; +// text_area("description",$value); + echo ""; + break; + + case "image": + echo "Current Image:"; + echo " + "; + if ($value != "") + { + echo " + + + Delete this image: + + Yes + No + + "; + } + echo " + New Image:"; + break; + + default: + GLM_TOOLBOX::html_error("Incorrect Value -> ".$key,1); + break; + } +} +if (isset($id)) { + ?> + + + + + + '; +GLM_TOOLBOX::footer(); +?> diff --git a/admin/Photos/edit_photo_category.phtml b/admin/Photos/edit_photo_category.phtml new file mode 100755 index 0000000..8092102 --- /dev/null +++ b/admin/Photos/edit_photo_category.phtml @@ -0,0 +1,149 @@ +db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG,1); + } + $row = $DB->db_fetch_array($res,0, PGSQL_ASSOC); + $qs2 = "select * from photo_category_bus where photocat_id = $id;"; + $res2 = $DB->db_exec($qs2); + if( pg_numrows( $res2 ) > 0 ) { + for( $i =0; $i < pg_numrows( $res2 ); $i++ ) { + $parent[] = pg_result( $res2, $i, 'buscat_id' ); + } + } +} else { + $row = array( "category" => ""); +} + +?> + +
    + '; +echo ' + Page to display on: + '.parent_select($parent).' + '; +foreach ($row as $key=>$value) { + switch ($key) { + + case "id": + echo ""; + break; + + case "pos": + echo ""; + break; + + case "category": + + echo 'Album Name: + + '; + break; + + case "intro": + echo "Intro:"; + GLM_TOOLBOX::text_area("intro",$value); + echo ""; + break; + + case "description": + echo "Description:"; + GLM_TOOLBOX::text_area("description",$value); + echo ""; + break; + + case "image": + if($value != "") { + echo " + "; + echo "Current Image: + + + + + Delete this image: + + + Yes + No + + "; + } + echo "New Image:\n"; + echo ""; + break; + + default: + GLM_TOOLBOX::html_error("Incorrect Value -> ".$key,1); + break; + } +} +if(isset($id)) { + $qs = "SELECT count(*) as count + FROM photo + WHERE catid = $id"; + + if(!$res = $DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,0); + } + + $row = $DB->db_fetch_array($res,0,PGSQL_ASSOC); + ?> + + + + + + +
    '; +GLM_TOOLBOX::footer(); +?> diff --git a/admin/Photos/export-images-is0.php b/admin/Photos/export-images-is0.php new file mode 100755 index 0000000..faa8623 --- /dev/null +++ b/admin/Photos/export-images-is0.php @@ -0,0 +1,53 @@ +setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); +$sql = " + SELECT id,image + FROM photo + WHERE image != '' + AND image not like 'is%' + ORDER BY 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 photo + SET image = :image + WHERE id = :id"; + $stmt3 = $db->prepare($prep2); + + foreach ($data as &$row) { + $row['image'] = trim($row['image']); + var_dump(OLDORG.$row['image']); + if (!ereg("^is", $row['image'])) { + $image_URL = OLDORG.$row['image']; + $image = $IServer->imageUpload($image_URL); + if ($image) { + try { + $stmt3->bindParam(":image", $image, PDO::PARAM_STR); + $stmt3->bindParam(":id", $row['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/admin/Photos/index.php b/admin/Photos/index.php new file mode 100644 index 0000000..d4380ca --- /dev/null +++ b/admin/Photos/index.php @@ -0,0 +1,3 @@ + diff --git a/admin/Photos/list_photo.phtml b/admin/Photos/list_photo.phtml new file mode 100755 index 0000000..4b9d14a --- /dev/null +++ b/admin/Photos/list_photo.phtml @@ -0,0 +1,87 @@ + "edit_photo.phtml?catid=$catid", + "List Photos" => "list_photo.phtml?catid=$catid", + "List Albums" => "list_photo_category.phtml" + ); +GLM_TOOLBOX::html_nav_table($lnav, 5); +$query = "select * from photo_category_bus;"; +if ($res2 = $DB->db_exec($query)) { + while ($row2 = pg_fetch_array($res2)) { + $data2[$row2['photocat_id']] = $row2['buscat_id']; + } +} +$qs2 = "SELECT id,title,pos + FROM photo + WHERE catid = $catid + ORDER BY pos"; +$res = $DB->db_exec($qs2); +if (!$res) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG, 1); +} +echo '
    '; +echo get_cat_name($data2[$catid]); +echo '
    '; +echo '
    +'; +?> + + + + +db_numrows($res); $i++) +{ + $row = $DB->db_fetch_array($res,$i, PGSQL_ASSOC); + if(!$row[id]) + { + GLM_TOOLBOX::html_error(DB_ERROR_MSG,1); + } + if(!$row[id]) + { + GLM_TOOLBOX::html_error(DB_ERROR_MSG,1); + } + ?> + + + + + + +'; +GLM_TOOLBOX::footer(); +?> diff --git a/admin/Photos/list_photo_category.phtml b/admin/Photos/list_photo_category.phtml new file mode 100755 index 0000000..a1e1cd6 --- /dev/null +++ b/admin/Photos/list_photo_category.phtml @@ -0,0 +1,99 @@ +db_exec($sql)) { + while ($row2 = pg_fetch_array($res2)) { + $data2[$row2['buscat_id']][] = $row2['photocat_id']; + } +} +GLM_TOOLBOX::top("Photo Albums (List Categories)", HELP_BASE."photocat.phtml?key=list"); +$lnav["Add A New Album"] = "edit_photo_category.phtml"; +//$lnav["Default Text"] = "edit-default.php"; +//$lnav["List Albums"] = "list_photo_category.phtml"; +GLM_TOOLBOX::html_nav_table($lnav, 7); +echo ' +
    Function Title
    + [Edit/Delete] + db_exec($qs)) + { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,0); + } + $max_data = $DB->db_fetch_array($maxresult,0,PGSQL_ASSOC); + $maxpos = $max_data['maxpos']; + $pos = "
    '; +?> + + + + + + $row3) { + $qs = "select pc.id,pc.category,pcb.pos + from photo_category pc left outer join photo_category_bus pcb on (pcb.photocat_id = pc.id) + where pcb.buscat_id = ".$buscat." order by pcb.pos;"; + if (!$res = $DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,1); + } + echo ' + + '; + for ($i = 0; $i < $DB->db_numrows( $res ); $i++) { + $row = $DB->db_fetch_array($res, $i, PGSQL_ASSOC); + if (!$row['id']) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG, 1); + } + ?> + + + + + + +'; +GLM_TOOLBOX::footer(); +?> diff --git a/admin/Photos/photo-setup.inc b/admin/Photos/photo-setup.inc new file mode 100644 index 0000000..d228853 --- /dev/null +++ b/admin/Photos/photo-setup.inc @@ -0,0 +1,304 @@ + + * @copyright 2009 Gaslight Media + * @license Gaslight Media + * @version CVS: $Id: photo-setup.inc,v 1.6 2009/10/16 15:09:11 matrix Exp $ + * @link <> + */ + +/** + * Description for define + */ +define("LEVELS_DEEP", 5); +// create a global database object +$DB = new GLM_DB(); + +/** + * $GLOBALS['DB'] + * @global mixed $GLOBALS['DB'] + * @name $DB + */ +$GLOBALS['DB'] = $DB; +// {{{ get_cat_name() +/** + * get_cat_name + * get the name of the category and the parent up to 4 levels + * + * @param mixed $id id for table bus_category + * + * @access public + * @return void + */ +function get_cat_name($id) +{ + $DB =& $GLOBALS['DB']; + if (is_numeric($id) && $id != 0) { + $query = " + SELECT category,parent + FROM bus_category + WHERE id = $id;"; + $res = $DB->db_exec($query); + $category = pg_result($res, 0, 'category'); + $parent = pg_result($res, 0, 'parent'); + $cats[] = strip_tags($category); + if ($parent != '0') { + $query = " + SELECT category,parent + FROM bus_category + WHERE id = $parent;"; + $res = $DB->db_exec( $query); + $category = pg_result($res, 0, 'category'); + $parent = pg_result($res, 0, 'parent'); + $cats[] = strip_tags($category); + if ($parent != '0') { + $query = " + SELECT category,parent + FROM bus_category + WHERE id = $parent;"; + $res = $DB->db_exec( $query); + $category = pg_result($res, 0, 'category'); + $parent = pg_result($res, 0, 'parent'); + $cats[] = strip_tags($category); + if ($parent != '0') { + $query = " + SELECT category,parent + FROM bus_category + WHERE id = $parent;"; + $res = $DB->db_exec( $query); + $category = pg_result($res, 0, 'category'); + $parent = pg_result($res, 0, 'parent'); + $cats[] = strip_tags($category); + } + } + } + $cats = array_reverse($cats); + return implode(" > ", $cats); + } else { + return false; + } +} +// }}} +// {{{ photo_process_image() +/** + * photo_process_image function for image processing + * + * @param mixed $image The variable of the image being post from the form + * @param mixed $image_name The variable_name of the image being post + * @access public + * @return void + */ +function photo_process_image($image, $image_name) +{ + $image_upload_array = GLM_TOOLBOX::img_upload($image, $image_name, PHOTO_LARGE_DIR); + GLM_TOOLBOX::img_resize(PHOTO_LARGE_DIR.$image_upload_array[0], + PHOTO_LARGE_DIR.$image_upload_array[0], PHOTO_LARGE_SIZE); + GLM_TOOLBOX::img_resize(PHOTO_LARGE_DIR.$image_upload_array[0], + PHOTO_SMALL_DIR.$image_upload_array[0], PHOTO_SMALL_SIZE); + $image_name = $image_upload_array[0]; + return $image_name; +} +// }}} +// {{{ sort_by_parent() +/** + * sort_by_parent + * + * @param mixed $data + * @access public + * @return void + */ +function sort_by_parent($data) +{ + if (!is_array($data)) { + return false; + } + foreach($data as $key=>$value) { + $data_new[$value["parent"]][$value["id"]] = $value; + } + return $data_new; +} +// }}} +// {{{ convertParent() +/** + * convertParent + * + * @param mixed $threads + * @param mixed $thread + * @access public + * @return void + */ +function convertParent($threads,$thread) +{ + static $select,$count; + if (!$count) { + $count = 0; + } + $bgcolor[] = '#ccc'; + $bgcolor[] = '#ddd'; + if (is_array($thread)) { + foreach($thread as $parent=>$value) { + $color = $bgcolor[$count]; + $select[$value["id"]]["color"] = $color; + $select[$value["id"]]["category"] = $value["category"]; + $select[$value["id"]]["count"] = $count; + + if (isset($threads[$parent])) { + $count++; + convertParent($threads, $threads[$parent]); + } + } + } + $count--; + return $select; +} +// }}} +// {{{ parent_select() +/** + * parent select + * + * This function does both the bus and bus category page parent select drop down + * boxes. The backcount var is used to lock the list to a certain level set up + * with define of LEVELS_DEEP. Count varl starts at one and is generated in the + * function convertParent so we'll need to subtract one for proper results. + * To unset backcount properly we'll need to check if count goes under or + * equals that of backcount. Then unset($backcount) cause if backcount is not + * empty then category won't get added to list. + * + * @return string + */ +function parent_select($catid) +{ + // select catid portion + $qs = " + SELECT id,category,parent + FROM bus_category + ORDER BY parent,pos"; + + $res = $GLOBALS['DB']->db_exec( $qs); + while ($row = pg_fetch_array($res)) { + $data[] = $row; + } + $data1 = sort_by_parent($data); + $select = '
    Function Gallery Name
    + Toggle Exp/Col + '.get_cat_name($buscat).' +
    '; + +echo ""; +if(isset($id) && $id != "") { + $qs = "SELECT bc.id as catid, bcb.id as id,bc.category,bcb.pos + FROM bus_category bc,bus_category_bus bcb,bus b + WHERE bcb.busid = $id + AND bcb.catid = bc.id + AND b.id = bcb.busid + ORDER BY bc.category"; + + if(!$altres = $DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,0); + } + + for($rel=0;$rel<$DB->db_numrows($altres);$rel++) { + $altrow = $DB->db_fetch_array($altres,$rel,PGSQL_ASSOC); + if( is_array( $oldalt ) ){ + $oldalt[$rel] = array_merge_recursive($altrow,$oldalt); + } else { + $oldalt[$rel] = $altrow; + } + } + } + ?> + + +"; + +foreach($fields as $key=>$value) { + if($value['type'] == "text") { + ?> + + + + '; + echo ''; + } elseif($value['type'] == "img") { + ?> + + "; + if($row[$value['name']] != "") { + echo ""; + echo " + + + + + "; + } + echo ""; + echo ""; + echo ""; + } elseif ($value['type'] == "file") { + ?> + + "; + if($row[$value['name']] != "") { + echo ""; + echo " + + + + + "; + } + echo ""; + echo ""; + echo ""; + } + if($value['type'] == "desc") { + echo ""; + echo ''; + echo ""; + } elseif($value['type'] == "hide") { + echo ""; + } elseif($value['type'] == "bool") { + echo ""; + } +} +echo ' + + + '; +if( is_numeric( $id ) ) { + echo ' + + + + + '; +} +echo ' + + + + + + + + + + '; +echo ''; +if(isset($id)) { + ?> + + +
    Pages:
    + + db_numrows($altcats);$i++) { + $altrow = $DB->db_fetch_array($altcats,$i,PGSQL_ASSOC); + for($a=0;$a + + + + +


    '.$value["name"].'
    Current Image: +
    Delete this image: + Yes + No +
    New $value[title]:
    Current File:".$row[$value['name']]." +
    Delete this File: + Yes + No +
    New $value[title]:
    $value[title]:
    $value[title]:"; + echo ''; + echo "
    File Uploads
    Current Files: +
    + To reposition the files use the drop down numbers to reposition them. + this updates the position of the files but any changes in filenames or updated files are not saved. + Make sure to reposition before making any other changes to files. +
    +
    +
    +
    +
    + '; +echo ' +
    +
    + + + +
    + + +'; +if( $id ) { + echo ' + + '; +} + +GLM_TOOLBOX::footer(); +?> + \ No newline at end of file diff --git a/admin/Toolbox/edit_bus_category.phtml b/admin/Toolbox/edit_bus_category.phtml new file mode 100755 index 0000000..a1566af --- /dev/null +++ b/admin/Toolbox/edit_bus_category.phtml @@ -0,0 +1,376 @@ +db_exec($sql)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG,1); + } + $row = $DB->db_fetch_array($res,0, PGSQL_ASSOC); + if (!$row[id]){ + GLM_TOOLBOX::html_error(DB_ERROR_MSG,1); + } +} else { + if (is_array($select_part)) { + foreach ($select_part as $fieldrow) { + $row[$fieldrow] = ($fieldrow == 'template') ? "1": ""; + } + } +} +if (defined("MEMBERS_DB") && MEMBERS_DB == 1) { + $memb_types_all = get_memb_all_types(&$DB); + if ($memb_data = get_memb_types(&$DB)) { + $member_sel = ''; + } + if ($id) { + $query = "select * from bus_cat_member where catid = $id;"; + if ($bcmData = $DB->db_auto_get_data($query)) { + foreach($bcmData as $bcmRow) { + $bus_cat_member_text .= '
    '; + $bus_cat_member_text .= 'Delete'; + $bus_cat_member_text .= $memb_types_all[$bcmRow['memb_type']]; + $bus_cat_member_text .= ''; + $bus_cat_member_text .= '
    '; + } + } + } +} +echo ''; +echo '
    '; +echo ''; +if (defined("MEMBERS_DB") && MEMBERS_DB == 1) { + echo ' + + '; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; +} + +foreach ($row as $key => $value) { + switch ($key) { + // {{{ case "id": + case "id": + echo ""; + break; + // }}} + // {{{ case "pos": + case "pos": + echo ""; + break; + // }}} + // {{{ case "section_links": + case "section_links": + echo ''; + $output = ''; + break; + // }}} + // {{{ case "no_search_form": + case "no_search_form": + echo ''; + $output = ''; + break; + // }}} + // {{{ case "include_member_map": + case "include_member_map": + echo ''; + $output = ''; + break; + // }}} + // {{{ case "featured": + case "featured": + echo ''; + $output = ' +
    Link to Member Listing (click to show/hide)
    Current Member-Links
    '.$bus_cat_member_text.'
    Link to Member Listing
    Search
    Search
    Map
    Home Page Headlines
    '; + echo ''.$output.''; + echo ''; + break; + // }}} + // {{{ case "feature_intro": + case "feature_intro": + break; + // }}} + // {{{ case "parent": + case "parent": + echo " + + Parent Page:"; + $output = parent_select($value,$id); + echo "".$output.""; + echo ""; + break; + // }}} + // {{{ case "category": + case "category": + echo "Navigation Name:"; + GLM_TOOLBOX::text_box("category",$value); + echo ""; + break; + // }}} + // {{{ case "imagename": + case "imagename": + echo "Image Caption:"; + GLM_TOOLBOX::text_box("imagename",$value); + echo ""; + break; + // }}} + // {{{ case "intro": + case "intro": + echo "Page Title:"; + GLM_TOOLBOX::text_box("intro",$value); + echo ""; + break; + // }}} + // {{{ case "image": + case "image": + echo "Current Image:"; + echo " + "; + if ($value != "") { + echo " + + + Delete this image: + + Yes + No + + "; + } + echo " + New Image:"; + break; + // }}} + // {{{ case "description": + case "description": + echo "Description:"; + echo ''; + echo ""; + break; + // }}} + // {{{ case "keyword": + case "keyword": + echo "Keyword:"; + GLM_TOOLBOX::text_box("keyword",$value); + echo ""; + break; + // }}} + // {{{ case "short_url": + case "short_url": + echo ' + Short URL: + '.BASE_URL.'/
    + NOTE: Short URL\'s Must not contain any spaces or non alpha characters.
    + Only a-z 0-9 _(underscore) -(dash) allowed. + + '; + break; + // }}} + // {{{ case "template": + case "template": + echo "Templates:"; + echo ' + + '; + echo ''; + for($i = 1; $i <= 6; ++$i): + echo ' + + '; + endfor; + echo ' + '; + echo ''; + for($i = 1; $i <= 6; ++$i): + echo ' + + '; + endfor; + echo ' + '; + echo ''; + for($i = 1; $i <= 6; ++$i): + echo ' + + '; + endfor; + echo ' +
    Template'.$i.'
    '.$i.'
    + + '; + break; + // }}} + // {{{ case "title": + case "title": + if ((GLM_HOST_ID == 'PRODUCTION' && $_SERVER['PHP_AUTH_USER'] == 'MediaAdmin') + || GLM_HOST != 'PRODUCTION') { + echo "Title Tag:"; + GLM_TOOLBOX::text_box("title", $value); + echo ""; + } else { + echo ''; + } + break; + // }}} + // {{{ case "meta_descr": + case "meta_descr": + if ((GLM_HOST_ID == 'PRODUCTION' && $_SERVER['PHP_AUTH_USER'] == 'MediaAdmin') + || GLM_HOST != 'PRODUCTION') { + echo ' + Meta Description: + + + + '; + } else { + echo ''; + } + break; + // }}} + // {{{ case "region": + case "region": + $regionsArray[''] = '-- Counties --'; + $sql = " + SELECT * + FROM region + ORDER BY region_name"; + try { + $stmt = $dbh->query($sql); + while ($regionRow = $stmt->fetch(PDO::FETCH_ASSOC)) { + if (!is_numeric($regionRow['region_name'])) { + $regionsArray[$regionRow['region_id']] = $regionRow['region_name']; + } + } + } catch(PDOException $e) { + Toolkit_Common::handleError($e); + } + echo "Counties:"; + echo ''.GLM_TOOLBOX::build_picklist('region', $regionsArray, $value).''; + echo ""; + break; + // }}} + // {{{ default: + default: + GLM_TOOLBOX::html_error("Incorrect Value -> ".$key,1); + break; + // }}} + } +} +echo ''; +if (defined("MEMBERS_DB") && MEMBERS_DB == 1) { + echo ''; +} +if (isset($id)) { + $qs = "SELECT count(*) as count + FROM bus_category_bus + WHERE catid = $id"; + + if (!$res = $DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,0); + } + + $row = $DB->db_fetch_array($res,0,PGSQL_ASSOC); + echo ' + + + '; + if (defined("CAT_LOCK") && !CAT_LOCK && !check_lock($id)) { + echo ' + + '; + } + echo ''; +} else { + GLM_TOOLBOX::form_footer("Insert", "", 2); +} +echo "
    "; +GLM_TOOLBOX::footer(); +?> diff --git a/admin/Toolbox/expand.png b/admin/Toolbox/expand.png new file mode 100755 index 0000000..38dcfc0 Binary files /dev/null and b/admin/Toolbox/expand.png differ diff --git a/admin/Toolbox/export-images-is0.php b/admin/Toolbox/export-images-is0.php new file mode 100755 index 0000000..9c795ee --- /dev/null +++ b/admin/Toolbox/export-images-is0.php @@ -0,0 +1,84 @@ +setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); +$sql = " +SELECT id,image +FROM bus_category +WHERE image != '' +ORDER BY id"; +//$sql .= " LIMIT 1 OFFSET 0"; +$pre1 = " +SELECT id,image +FROM bus +WHERE image != ''"; +//$pre1 .= " LIMIT 1 OFFSET 0"; +try { + $stmt = $db->query($sql); + $data = $stmt->fetchAll(PDO::FETCH_ASSOC); + $stmt2 = $db->query($pre1); + $data2 = $stmt2->fetchAll(PDO::FETCH_ASSOC); + echo '
    ';
    +    print_r($data);
    +    print_r($data2);
    +    echo '
    '; +} catch(PDOException $e) { + die($e->getMessage()); +} +$db->beginTransaction(); +$IServer = new Toolkit_Image_Server(); +if (is_array($data)) { + $prep2 = " + UPDATE bus_category + SET image = :image + WHERE id = :id"; + $stmt3 = $db->prepare($prep2); + + foreach ($data as &$row) { + $image_URL = OLDORG.$row['image']; + $image = $IServer->imageUpload($image_URL); + if ($image) { + try { + $stmt3->bindParam(":image", $image, PDO::PARAM_STR); + $stmt3->bindParam(":id", $row['id'], PDO::PARAM_INT); + $stmt3->execute(); + } catch(PDOException $e) { + die($e->getMessage()); + } + } + echo '
    Image Name Returned: '; + var_dump($image); + } +} +if (is_array($data2)) { + $prep3 = " + UPDATE bus + SET image = :image + WHERE id = :id"; + $stmt4 = $db->prepare($prep3); + foreach ($data2 as &$row2) { + echo '
    '.print_r($row2, true).'
    '; + if (preg_match("/^is/",$row2['image'])) { + continue; + } + $image_URL = OLDORG.$row2['image']; + echo '
    '.print_r($image_URL, true).'
    '; + $image = $IServer->imageUpload($image_URL); + if ($image) { + try { + $stmt4->bindParam(":image", $image, PDO::PARAM_STR); + $stmt4->bindParam(":id", $row2['id'], PDO::PARAM_INT); + $stmt4->execute(); + } catch(PDOException $e) { + die($e->getMessage()); + } + } + echo '
    Image Name Returned: '; + var_dump($image); + } +} +$db->commit(); +//$db->rollBack(); +?> diff --git a/admin/Toolbox/file-repos-xml.php b/admin/Toolbox/file-repos-xml.php new file mode 100644 index 0000000..1d947bf --- /dev/null +++ b/admin/Toolbox/file-repos-xml.php @@ -0,0 +1,29 @@ +db_exec( "BEGIN WORK;" ); +if( $_GET['oldpos'] < $_GET['newpos'] ) +{ + $query = "update files + set pos = pos - 1 + where bus_id = ".$_GET['busid']." + and pos > ".$_GET['oldpos']." + and pos <= ".$_GET['newpos']." "; + $DB->db_exec( $query ); + $DB->db_exec( "update files set pos = ".$_GET['newpos']." where id = ".$_GET['id'] ); +} +else +{ + $query = "update files + set pos = pos + 1 + where bus_id = ".$_GET['busid']." + and pos >= ".$_GET['newpos']." + and pos < ".$_GET['oldpos']." "; + $DB->db_exec( $query ); + $DB->db_exec( "update files set pos = ".$_GET['newpos']." where id = ".$_GET['id'] ); +} +$DB->db_exec( "COMMIT WORK;" ); +?> diff --git a/admin/Toolbox/file-xml.php b/admin/Toolbox/file-xml.php new file mode 100644 index 0000000..f54c5f8 --- /dev/null +++ b/admin/Toolbox/file-xml.php @@ -0,0 +1,60 @@ +db_auto_get_data( $query ) ) +{ + $total = count( $file_data ); + for( $i = 1; $i <= $total; $i++ ) + { + $poses[$i] = $i; + } + foreach( $file_data as $file_row ) + { + $filename = ($file_row['urltext']) ? $file_row['urltext']: $file_row['filename']; + $out .= '
    +

    File '.$file_row["pos"].': + + + '.$filename.'

    '; + $out .= '

    '; + if( is_array( $poses ) ) + { + $out .= ' +
    + File URL text: + +
    + +
    +

    + '; + } +} +echo $out; +?> diff --git a/admin/Toolbox/file_load.js b/admin/Toolbox/file_load.js new file mode 100644 index 0000000..6192717 --- /dev/null +++ b/admin/Toolbox/file_load.js @@ -0,0 +1,5 @@ +function add_file() +{ + var myForm = document.getElementById('myForm'); + var newFile = document.createElement('fileUpload'); +} diff --git a/admin/Toolbox/files.sql b/admin/Toolbox/files.sql new file mode 100644 index 0000000..b148ca5 --- /dev/null +++ b/admin/Toolbox/files.sql @@ -0,0 +1,63 @@ +-- +-- PostgreSQL database dump +-- + +SET client_encoding = 'SQL_ASCII'; +SET check_function_bodies = false; + +SET SESSION AUTHORIZATION 'postgres'; + +SET search_path = public, pg_catalog; + +-- +-- TOC entry 3 (OID 15572607) +-- Name: files; Type: TABLE; Schema: public; Owner: postgres +-- + +CREATE TABLE files ( + id serial NOT NULL, + filename text, + bytes integer, + "type" text, + urltext text, + bus_id integer, + pos integer DEFAULT >= 1 +); + + +-- +-- TOC entry 4 (OID 15572607) +-- Name: files; Type: ACL; Schema: public; Owner: postgres +-- + +REVOKE ALL ON TABLE files FROM PUBLIC; +GRANT ALL ON TABLE files TO nobody; + + +-- +-- TOC entry 5 (OID 15572607) +-- Name: files_id_seq; Type: ACL; Schema: public; Owner: postgres +-- + +REVOKE ALL ON TABLE files_id_seq FROM PUBLIC; +GRANT ALL ON TABLE files_id_seq TO nobody; + + +-- +-- TOC entry 6 (OID 15572613) +-- Name: files_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY files + ADD CONSTRAINT files_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 7 (OID 15572619) +-- Name: $1; Type: FK CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY files + ADD CONSTRAINT "$1" FOREIGN KEY (bus_id) REFERENCES bus(id) ON DELETE CASCADE; + + diff --git a/admin/Toolbox/htmlarea.css b/admin/Toolbox/htmlarea.css new file mode 100644 index 0000000..23bdf7d --- /dev/null +++ b/admin/Toolbox/htmlarea.css @@ -0,0 +1,180 @@ +.htmlarea { background: #fff; } + +.htmlarea .toolbar { + cursor: default; + background: ButtonFace; + padding: 1px 1px 2px 1px; + border: 1px solid; + border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; +} +.htmlarea .toolbar table { font-family: tahoma,verdana,sans-serif; font-size: 11px; } +.htmlarea .toolbar img { border: none; } +.htmlarea .toolbar .label { padding: 0px 3px; } + +.htmlarea .toolbar .button { + background: ButtonFace; + color: ButtonText; + border: 1px solid ButtonFace; + padding: 1px; + margin: 0px; +} +.htmlarea .toolbar .buttonHover { + border: 1px solid; + border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; +} +.htmlarea .toolbar .buttonActive, .htmlarea .toolbar .buttonPressed { + padding: 2px 0px 0px 2px; + border: 1px solid; + border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow; +} +.htmlarea .toolbar .buttonPressed { + background: ButtonHighlight; +} +.htmlarea .toolbar .indicator { + padding: 0px 3px; + overflow: hidden; + width: 20px; + text-align: center; + cursor: default; + border: 1px solid ButtonShadow; +} + +.htmlarea .toolbar .buttonDisabled { background-color: #aaa; } + +.htmlarea .toolbar .buttonDisabled img { + filter: alpha(opacity = 25); + -moz-opacity: 25%; +} + +.htmlarea .toolbar .separator { + position: relative; + margin: 3px; + border-left: 1px solid ButtonShadow; + border-right: 1px solid ButtonHighlight; + width: 0px; + height: 16px; + padding: 0px; +} + +.htmlarea .toolbar .space { width: 5px; } + +.htmlarea .toolbar select { font: 11px Tahoma,Verdana,sans-serif; } + +.htmlarea .toolbar select, +.htmlarea .toolbar select:hover, +.htmlarea .toolbar select:active { background: FieldFace; color: ButtonText; } + +.htmlarea .statusBar { + border: 1px solid; + border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow; + padding: 2px 4px; + background-color: ButtonFace; + color: ButtonText; + font: 11px Tahoma,Verdana,sans-serif; +} + +.htmlarea .statusBar .statusBarTree a { + padding: 2px 5px; + color: #00f; +} + +.htmlarea .statusBar .statusBarTree a:visited { color: #00f; } +.htmlarea .statusBar .statusBarTree a:hover { + background-color: Highlight; + color: HighlightText; + padding: 1px 4px; + border: 1px solid HighlightText; +} + + +/* Hidden DIV popup dialogs (PopupDiv) */ + +.dialog { + color: ButtonText; + background: ButtonFace; +} + +.dialog .content { padding: 2px; } + +.dialog, .dialog button, .dialog input, .dialog select, .dialog textarea, .dialog table { + font: 11px Tahoma,Verdana,sans-serif; +} + +.dialog table { border-collapse: collapse; } + +.dialog .title { + background: #008; + color: #ff8; + border-bottom: 1px solid #000; + padding: 1px 0px 2px 5px; + font-size: 12px; + font-weight: bold; + cursor: default; +} + +.dialog .title .button { + float: right; + border: 1px solid #66a; + padding: 0px 1px 0px 2px; + margin-right: 1px; + color: #fff; + text-align: center; +} + +.dialog .title .button-hilite { border-color: #88f; background: #44c; } + +.dialog button { + width: 5em; + padding: 0px; +} + +.dialog .buttonColor { + padding: 1px; + cursor: default; + border: 1px solid; + border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; +} + +.dialog .buttonColor-hilite { + border-color: #000; +} + +.dialog .buttonColor .chooser, .dialog .buttonColor .nocolor { + height: 0.6em; + border: 1px solid; + padding: 0px 1em; + border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow; +} + +.dialog .buttonColor .nocolor { padding: 0px; } +.dialog .buttonColor .nocolor-hilite { background-color: #fff; color: #f00; } + +.dialog .label { text-align: right; width: 6em; } +.dialog .value input { width: 100%; } +.dialog .buttons { text-align: right; padding: 2px 4px 0px 4px; } + +.dialog legend { font-weight: bold; } +.dialog fieldset table { margin: 2px 0px; } + +.popupdiv { + border: 2px solid; + border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; +} + +.popupwin { + padding: 0px; + margin: 0px; +} + +.popupwin .title { + background: #fff; + color: #000; + font-weight: bold; + font-size: 120%; + padding: 3px 10px; + margin-bottom: 10px; + border-bottom: 1px solid black; + letter-spacing: 2px; +} + +form { margin: 0px; border: none; } diff --git a/admin/Toolbox/images/collapse.png b/admin/Toolbox/images/collapse.png new file mode 100755 index 0000000..d10e051 Binary files /dev/null and b/admin/Toolbox/images/collapse.png differ diff --git a/admin/Toolbox/images/expand.png b/admin/Toolbox/images/expand.png new file mode 100755 index 0000000..38dcfc0 Binary files /dev/null and b/admin/Toolbox/images/expand.png differ diff --git a/admin/Toolbox/index.phtml b/admin/Toolbox/index.phtml new file mode 100755 index 0000000..550afb8 --- /dev/null +++ b/admin/Toolbox/index.phtml @@ -0,0 +1,3 @@ + diff --git a/admin/Toolbox/jake-handler.js b/admin/Toolbox/jake-handler.js new file mode 100644 index 0000000..efd60c1 --- /dev/null +++ b/admin/Toolbox/jake-handler.js @@ -0,0 +1,49 @@ +function getHTTPObject() +{ + var http = false; + + if (window.XMLHttpRequest) { // Mozilla, Safari,... + http = new XMLHttpRequest(); + if (http.overrideMimeType) { + http.overrideMimeType('text/html'); + } + } else if (window.ActiveXObject) { // IE + try { + http = new ActiveXObject("Msxml2.XMLHTTP"); + } catch (e) { + try { + http = new ActiveXObject("Microsoft.XMLHTTP"); + } catch (e) {} + } + } + return http; +} +function get_files( id ) +{ + var http = getHTTPObject(); // We create the HTTP Object + var url = "file-xml.php?id=" + id + "&ms="; + http.open("GET", url + "&ms=" + new Date().getTime(),true); + http.onreadystatechange = function() + { + if(http.readyState == 4) + { + document.getElementById('file-uploads').innerHTML = http.responseText; + } + } + http.send(null); +} +function update_file_pos( busid, id, oldpos, newpos ) +{ + var http = getHTTPObject(); // We create the HTTP Object + var url = "file-repos-xml.php?busid=" + busid + "&id=" + id + "&oldpos=" + oldpos + "&newpos=" + newpos; + http.open("GET", url + "&ms=" + new Date().getTime(),true); + http.onreadystatechange = function() + { + if(http.readyState == 4) + { + document.getElementById('file-uploads-data').innerHTML = http.responseText; + get_files( busid ); + } + } + http.send(null); +} diff --git a/admin/Toolbox/list_bus.phtml b/admin/Toolbox/list_bus.phtml new file mode 100755 index 0000000..d3f3974 --- /dev/null +++ b/admin/Toolbox/list_bus.phtml @@ -0,0 +1,80 @@ +db_exec($qs)) +{ + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,1); +} +$catrow = $DB->db_fetch_array($catres,0,PGSQL_ASSOC); +$qs = "SELECT b.id,b.name,bcb.pos + FROM bus b,bus_category_bus bcb + WHERE bcb.catid = $catid + AND b.id = bcb.busid + AND bcb.catid = $catid + ORDER BY bcb.pos"; +if(!$res = $DB->db_exec($qs)) +{ + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,1); +} +GLM_TOOLBOX::top("$catrow[category] Paragraphs", HELP_BASE."bus.phtml?key=list","ToolboxUserGuide_2.0"); +$toolbox_nav["Add New Paragraph"] = "edit_bus.phtml?catid=$catid"; +unset($toolbox_nav["Add A New Page"]); +GLM_TOOLBOX::html_nav_table($toolbox_nav, 6); +echo '
    + + + + +'; +for($i = 0; $i < $DB->db_numrows($res); $i++) +{ + $row = $DB->db_fetch_array($res,$i, PGSQL_ASSOC); + echo ' + + '; +} +echo '
    Function Records
    +
    '; +GLM_TOOLBOX::footer(); +?> diff --git a/admin/Toolbox/list_bus_category.phtml b/admin/Toolbox/list_bus_category.phtml new file mode 100755 index 0000000..e0f927e --- /dev/null +++ b/admin/Toolbox/list_bus_category.phtml @@ -0,0 +1,177 @@ +'; +if(isset($active)) { + if($active=="t") { + $nd = "f"; + } else { + $nd = "y"; + } + $query = "UPDATE bus_category SET active = '$nd' WHERE id = $id"; + $DB->db_exec($query); + GLM_TOOLBOX::create_sitemap(); + $toolbox->cache->clean('Nav'); +} +$toolbox_nav["Edit Positions"] = "list_bus_category.phtml?show_pos=1"; +$toolbox_nav["Expand All"] = "list_bus_category.phtml?expand_all=1"; +$toolbox_nav["Collapse All"] = "list_bus_category.phtml?collaspe_all=1"; +GLM_TOOLBOX::html_nav_table($toolbox_nav, 6); +echo ' + + + + +
    +
    + + +
    +
    +
    +'; +include_once("threads.phtml"); +if( !isset( $cat_search ) || $cat_search == '' ) { + $qs = "SELECT id,parent,pos,category,active,keyword + FROM bus_category + WHERE parent is not null + ORDER BY pos;"; + + if(!$res = $DB->db_exec($qs)) { + echo "Failure".$qs; + } + for($i=0;$i'; + if($data['active'] == "t") { + $active .= "\"Don't"; + } else { + $active .= "\"Display\""; + } + } elseif($data['id']==HOME_ID) { + $active = " "; + } + if($show_pos && !in_array($id,$category_locks)) { + $qs = "SELECT MAX(pos) as maxpos + FROM bus_category + WHERE parent = $parent"; + + if(!$maxresult = $DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,0); + } + $max_data = $DB->db_fetch_array($maxresult,0,PGSQL_ASSOC); + $maxpos = $max_data['maxpos']; + $pos = '
    +'; +GLM_TOOLBOX::footer(); +?> diff --git a/admin/Toolbox/member-code-line.php b/admin/Toolbox/member-code-line.php new file mode 100644 index 0000000..6d4a5f2 --- /dev/null +++ b/admin/Toolbox/member-code-line.php @@ -0,0 +1,16 @@ +pgsql_select( $query ) ){ + $out = '
    '; + $out .= 'Delete '; + $out .= $data[0]['class_code'].' '.$data[0]['name']; + $out .= ''; + $out .= '
    '; + } +} +echo $out; +?> diff --git a/admin/Toolbox/member-code-query.php b/admin/Toolbox/member-code-query.php new file mode 100644 index 0000000..744b82a --- /dev/null +++ b/admin/Toolbox/member-code-query.php @@ -0,0 +1,36 @@ +pgsql_select( $query ) ){ + $out = '
    '; + $out .= '
    '; +} +echo $out; +?> diff --git a/admin/Toolbox/member-toolbox.js b/admin/Toolbox/member-toolbox.js new file mode 100644 index 0000000..e090c19 --- /dev/null +++ b/admin/Toolbox/member-toolbox.js @@ -0,0 +1,37 @@ +var MemberToolbox = +{ + init: function() + { + if ($("#add-member-area")) { + $.ajax({ + url: "member-code-query.php", + data: "Option=category", + cache: false, + success: function(html, textStatus) { + $("#add-member-area").html(html); + $("#add-code").click(function() { + MemberToolbox.addCodes(); + return false; + }); + } + }); + } + }, + + addCodes: function() + { + var category_id = $("#newCategory").val(); + $.ajax({ + url: "member-code-line.php", + cache: false, + data: "category_id=" + category_id, + success: function(html, textStatus) { + $("#list-members-info").append(html); + } + }); + + return false; + } +}; + +$(document).ready(MemberToolbox.init); diff --git a/admin/Toolbox/member-toolbox.php b/admin/Toolbox/member-toolbox.php new file mode 100644 index 0000000..6ef4db9 --- /dev/null +++ b/admin/Toolbox/member-toolbox.php @@ -0,0 +1,173 @@ +'; + $member_sel .= ''; + foreach( $memb_data as $memb_id => $memb_name ) + { + $member_sel .= ''; + } + $member_sel .= ' '; + } + if( $memb_sub_types = get_memb_sub_types( &$DB ) ) + { + foreach( $memb_sub_types as $parent => $memb_sub_value ) + { + $member_sub_sel[$parent] = ''; + } + } +} +?> +var addMemberLink = document.getElementById('add-member'); +var addMemberDiv = document.getElementById('add-member-area'); +var addMemberList = document.getElementById('list-members-info'); +function removeElement( elem ) +{ + var rem = document.getElementById( elem ); + rem.innerHTML = ''; +} +function attachEventListener(target, eventType, functionRef, capture) +{ + if (typeof target.addEventListener != "undefined") + { + target.addEventListener(eventType, functionRef, capture); + } + else if (typeof target.attachEvent != "undefined") + { + target.attachEvent("on" + eventType, functionRef); + } + else + { + eventType = "on" + eventType; + + if (typeof target[eventType] == "function") + { + var oldListener = target[eventType]; + + target[eventType] = function() + { + oldListener(); + + return functionRef(); + } + } + else + { + target[eventType] = functionRef; + } + } + + return true; +} +function addLoadListener(fn) +{ + if (typeof window.addEventListener != 'undefined') + { + window.addEventListener('load', fn, false); + } + else if (typeof document.addEventListener != 'undefined') + { + document.addEventListener('load', fn, false); + } + else if (typeof window.attachEvent != 'undefined') + { + window.attachEvent('onload', fn); + } + else + { + var oldfn = window.onload; + if (typeof window.onload != 'function') + { + window.onload = fn; + } + else + { + window.onload = function() + { + oldfn(); + fn(); + }; + } + } +} +function myLink() +{ + attachEventListener(addMemberLink,"click",addMyMember,false); +} +function addMyMember() +{ + addMemberDiv.innerHTML = ''; + addMemberDiv.innerHTML += 'Add'; + var addType = document.getElementById('add-member-type'); + attachEventListener(addType,"click",myAddType,false); + var addMemberType = document.getElementById('memb_type'); + attachEventListener(addMemberType,"change",myAddSubType,false); +} +function myAddSubType(){ + var sub_sel_hmtl = new Array(); + $html ) + { + ?> + sub_sel_hmtl[] = ''; + + var memb_type = document.getElementById('memb_type'); + var memType = memb_type.options[memb_type.selectedIndex].value + if( !isNaN( memType ) ) + { + var subPart = document.getElementById('sub-part'); + subPart.innerHTML = sub_sel_hmtl[memType]; + } +} +function myAddType() +{ + try{ + var membTypes = document.getElementById('memb_sub'); + if( membTypes.value ){ + var hideMemIdName = 'hideMember_' + membTypes.value; + var hideMemName = 'hideMember_' + membTypes.value; + addMemberList.innerHTML += '
    ' + + membTypes.options[membTypes.selectedIndex].text + + '' + + 'Delete
    '; + } + else{ + var membTypes = document.getElementById('memb_type'); + if( membTypes.value ){ + var hideMemIdName = 'hideMember_' + membTypes.value; + var hideMemName = 'hideMember_' + membTypes.value; + addMemberList.innerHTML += '
    ' + + membTypes.options[membTypes.selectedIndex].text + + '' + + 'Delete
    '; + } + } + } + catch(err){ + var membTypes = document.getElementById('memb_type'); + if( membTypes.value ){ + var hideMemIdName = 'hideMember_' + membTypes.value; + var hideMemName = 'hideMember_' + membTypes.value; + addMemberList.innerHTML += '
    ' + + membTypes.options[membTypes.selectedIndex].text + + '' + + 'Delete
    '; + } + } + addMemberDiv.innerHTML = 'Add Member Link'; + var addMemberLink = document.getElementById('add-member'); + attachEventListener(addMemberLink,"click",addMyMember,false); +} +addLoadListener(myLink); diff --git a/admin/Toolbox/threads.phtml b/admin/Toolbox/threads.phtml new file mode 100755 index 0000000..762cce9 --- /dev/null +++ b/admin/Toolbox/threads.phtml @@ -0,0 +1,62 @@ +'; + var $beginLevel2 = '
      '; + var $endLevel = '
    '; + var $beginItem = '
  • '; + var $beginItem2 = '
  • '; + var $endItem = '
  • '; + var $wholeThread; + + function __construct($code="") { + if(!empty($code)) { + $this->beginLevel = $code['beginLevel']; + $this->beginLevel2 = $code['beginLevel2']; + $this->endLevel = $code['endLevel']; + $this->beginItem = $code['beginItem']; + $this->beginItem2 = $code['beginItem2']; + $this->endItem = $code['endItem']; + } + } + + function sortChilds($threads) { + while(list($var, $value) = each($threads)) + $childs[$value[parent]][$value[ID]] = $value; + return $childs; + } + + function convertToThread($threads, $thread) { + static $count; + if( !$count ) { + $this->wholeThread .= $this->beginLevel2; + } else { + $this->wholeThread .= $this->beginLevel; + } + while(list($parent, $value) = each($thread)) { + if( $threads[$parent] && $value['closed'] ) { + $this->wholeThread .= $this->beginItem2; + $this->wholeThread .= ''; + } elseif( $threads[$parent] && !$value['closed'] ) { + $this->wholeThread .= $this->beginItem2; + $this->wholeThread .= ''; + } else { + $this->wholeThread .= $this->beginItem; + } + $count++; + $this->wholeThread .= " [Edit]  " + ."[Paragraphs]  " + ."[Preview]" + .$value[pos] + ."".$value[active]; + $this->wholeThread .= $value['content'] . "" . $this->endItem ."\n"; + if( $threads[$parent] && !$value['closed'] ) { + $this->convertToThread($threads, $threads[$parent]); + } + } + $this->wholeThread .= $this->endLevel; + return $this->wholeThread; + } +} +?> diff --git a/admin/Toolbox/toolbox_setup.inc b/admin/Toolbox/toolbox_setup.inc new file mode 100755 index 0000000..3d019a4 --- /dev/null +++ b/admin/Toolbox/toolbox_setup.inc @@ -0,0 +1,435 @@ + + * @copyright 2009 Gaslight Media + * @license Gaslight Media + * @version CVS: $Id: toolbox_setup.inc,v 1.5 2009/09/09 13:44:33 matrix Exp $ + * @link <> + */ +// {{{ INCLUDES +/** + * Main site config file + */ +include_once '../../setup.phtml'; + +/** + * GLM_DB class + */ +include_once BASE.'classes/class_db.inc'; + +/** + * GLM_TOOLBOX class + */ +include_once BASE.'classes/class_toolbox.inc'; + +/** + * GLM_TEMPLATE class + */ +include_once BASE.'classes/class_template.inc'; +// }}} +$DB =& new GLM_DB(); +$toolbox =& new GLM_TEMPLATE(1); +// {{{ DEFINES +if (!defined("DELUXE_TOOLBOX")) { + + /** + * Description for define + */ + define("DELUXE_TOOLBOX",0); +} +if (!defined("TOOLBOX_FLAGS")) { + + /** + * Description for define + */ + define("TOOLBOX_FLAGS",1); +} +if (!defined("LEVELS_DEEP")) +{ + + /** + * Description for define + */ + define("LEVELS_DEEP",5); +} +if (!defined("MEMBERS_DB")) { + + /** + * Description for define + */ + define("MEMBERS_DB",false); +} +if (!defined("HOME_ID")) { + + /** + * Description for define + */ + define("HOME_ID",1); +} +if (!defined("CAT_LOCK")) { + + /** + * Description for define + */ + define("CAT_LOCK",0); +} +if (!defined("MULTIPLE_CAT")) { + + /** + * Description for define + */ + define("MULTIPLE_CAT",0); +} +// }}} +$category_locks = array();//range(1,13); +// {{{ $fields = array(); +// $fields array used for the bus table edit page +$fields[] = array( + "name" => "id", + "title" => "id", + "type" => "hide" +); +$fields[] = array( + "name" => "name", + "title" => "Paragraph Title", + "type" => "text" +); +$fields[] = array( + "name" => "description", + "title" => "Description", + "type" => "desc" +); +$fields[] = array( + "name" => "imagename", + "title"=> "Image Caption", + "type" => "text" +); +$fields[] = array( + "name" => "image", + "title" => "Image", + "type" => "img" +); +$fields[] = array( + "name" => "back_to_top", + "title" => "Insert 'Back to Top' link", + "type" => "bool" +); +// }}} +// {{{ update_member_bus_cat() +/** + * Short description for function + * + * Long description (if any) ... + * + * @param object &$DB Parameter description (if any) ... + * @return boolean Return description (if any) ... + */ +function update_member_bus_cat(&$DB) +{ + if (!is_numeric($_REQUEST['id'])) { + return false; + } + $query = "select * from bus_cat_member where catid = ".$_REQUEST['id']; + if ($bcm_data = $DB->pgsql_select($query)) { + foreach ($bcm_data as $bcm_row) { + if (is_array($_REQUEST['member_cats']) && !in_array($bcm_row['memb_type'], $_REQUEST['member_cats'])) { + // delete this one by the bus_cat_member id + $DB->pgsql_delete('bus_cat_member', array('id'=>$bcm_row['id'])); + } elseif (is_array($_REQUEST['member_cats'])) { + $key = array_search($bcm_row['memb_type'], $_REQUEST['member_cats']); + unset($_REQUEST['member_cats'][$key]); + } + } + } + if (is_array($_REQUEST['member_cats'])) { + foreach ($_REQUEST['member_cats'] as $row) { + $data = array('catid'=>$_REQUEST['id'],'memb_type'=>$row); + $DB->pgsql_insert('bus_cat_member', $data, 'id', 'bus_cat_member_id_seq') ; + } + }else{ + // if there's no member_cats array then delete any that are in bus_cat_member table + $DB->pgsql_delete('bus_cat_member', array('catid'=>$_REQUEST['id'])) ; + } +} +// }}} +// {{{ get_sub() +/** + * Short description for function + * + * Long description (if any) ... + * + * @param unknown $catid Parameter description (if any) ... + * @param object $DB Parameter description (if any) ... + * @return array Return description (if any) ... + */ +function get_sub($catid, $DB) { + static $string,$count; + if (!isset($count)) { + $count = 0; + } + $string[$count] = $catid; + $count++; + $query = "SELECT id + FROM bus_category + WHERE parent = $catid + ORDER BY pos"; + if ($data = $DB->db_auto_get_data($query)){ + foreach($data as $key=>$value){ + $id = $value['id']; + $string = get_sub($id, $DB) ; + } + return $string; + }else{ + return $string; + } +} +// }}} +// {{{ get_prop_types() +/** + * Short description for function + * + * Long description (if any) ... + * + * @param object &$DB Parameter description (if any) ... + * @return array Return description (if any) ... + */ +function get_prop_types(&$DB) { + static $prop_types; + if (!is_array($prop_types)) { + $query = "select * from prop_type order by name;"; + if ($data = $DB->db_auto_get_data($query)) { + foreach ($data as $row) { + $prop_types[$row['id']] = $row['name']; + } + } + } + return $prop_types; +} +// }}} +// {{{ get_memb_sub_types() +/** + * Short description for function + * + * Long description (if any) ... + * + * @param object &$DB Parameter description (if any) ... + * @return array Return description (if any) ... + */ +function get_memb_sub_types(&$DB) { + static $memb_sub_types; + if (!is_array($memb_sub_types)) { + $query = "select category_id,name,parent_id from category where parent_id != 0 order by parent_id,pos"; + if ($data = $DB->pgsql_select($query)) { + foreach ($data as $row) { + $memb_sub_types[$row['parent_id']][$row['category_id']] = $row['name']; + } + } + } + return $memb_sub_types; +} +// }}} +// {{{ get_memb_types() +/** + * Short description for function + * + * Long description (if any) ... + * + * @param object &$DB Parameter description (if any) ... + * @return array Return description (if any) ... + */ +function get_memb_types(&$DB) { + static $memb_types; + if (!is_array($memb_types)) { + $query = "select * from category where parent_id = 0 order by pos;"; + if ($data = $DB->db_auto_get_data($query)) { + foreach ($data as $row) { + $memb_types[$row['category_id']] = $row['name']; + } + } + } + return $memb_types; +} +// }}} +// {{{ get_memb_all_types() +/** + * Short description for function + * + * Long description (if any) ... + * + * @param object &$DB Parameter description (if any) ... + * @return array Return description (if any) ... + */ +function get_memb_all_types(&$DB) { + static $memb_types; + if (!is_array($memb_types)) { + $query = "select * from category order by parent_id,pos;"; + if ($data = $DB->db_auto_get_data($query)) { + foreach ($data as $row) { + $memb_types[$row['category_id']] = $row['class_code'].' '.$row['name']; + } + } + } + return $memb_types; +} +// }}} +// {{{ check_lock() +/** + * Short description for function + * + * Long description (if any) ... + * + * @param mixed $id Parameter description (if any) ... + * @return boolean Return description (if any) ... + */ +function check_lock($id){ + if (isset($id) && $id != '' && is_numeric($id)) { + if (file_exists(BASE.'static/'.$id.'.phtml') || $id == HOME_ID) { + return true; + }else{ + return false; + } + }else{ + return false; + } + +} +// }}} +// {{{ sort_by_parent() +/** + * Short description for function + * + * Long description (if any) ... + * + * @param array $data Parameter description (if any) ... + * @return mixed Return description (if any) ... + */ +function sort_by_parent($data) { + if (!is_array($data)) + return false; + foreach($data as $key=>$value) { + $data_new[$value["parent"]][$value["id"]] = $value; + } + return $data_new; +} +// }}} +// {{{ convertParent() +/** + * Short description for function + * + * Long description (if any) ... + * + * @param array $threads Parameter description (if any) ... + * @param array $thread Parameter description (if any) ... + * @return array Return description (if any) ... + */ +function convertParent($threads,$thread) { + static $select,$count; + $count = (!isset($count)) ? 0: $count; + $bgcolor[] = '#6d6d6d'; + $bgcolor[] = '#7a7a7a'; + $bgcolor[] = '#8a8a8a'; + $bgcolor[] = '#979797'; + $bgcolor[] = '#adadad'; + $bgcolor[] = '#c1c1c1'; + if (is_array($thread)) { + foreach($thread as $parent=>$value) { + $color = $bgcolor[$count]; + $select[$value['id']]['color'] = $color; + $select[$value['id']]['category'] = $value['category']; + $select[$value['id']]['count'] = $count; + + if (isset($threads[$parent])) { + $count++; + convertParent($threads, $threads[$parent]); + } + } + } + $count--; + return $select; +} +// }}} +// {{{ parent_select() +/** + parent select + +

    This function does both the bus and bus category page parent select drop down boxes. + the backcount var is used to lock the list to a certain level set up with define of LEVELS_DEEP. + count varl starts at one and is generated in the function convertParent so we'll need to subtract one for proper results. + to unset backcount properly we'll need to check if count goes under or equals that of backcount. + then unset($backcount) cause if backcount is not empty then category won't get added to list. +

    + */ +function parent_select($catid,$id,$sel_name = "parent"){ + global $DB; + // select catid portion + $qs = "SELECT id,category,parent + FROM bus_category + ORDER BY parent,pos"; + + $data = $DB->db_auto_get_data($qs,CONN_STR); + $data1 = sort_by_parent($data); + $select = ""; + } + if ((($id==HOME_ID || in_array($id,$GLOBALS['category_locks'])) && $catid == 0)&& strstr($_SERVER['PHP_SELF'],"edit_bus_category") && ($catid!='' && $id!='')){ + $select = 'No Parent '; + } + return $select; +} +// }}} +$toolbox_nav['Toolbox Home'] = 'list_bus_category.phtml'; +if (!CAT_LOCK) { + $toolbox_nav["Add A New Page"] = "edit_bus_category.phtml"; +} +?> diff --git a/admin/Toolbox/update_bus.phtml b/admin/Toolbox/update_bus.phtml new file mode 100755 index 0000000..d7cf243 --- /dev/null +++ b/admin/Toolbox/update_bus.phtml @@ -0,0 +1,604 @@ +db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs, 0); + } + $data = $DB->db_fetch_array($result, 0, PGSQL_ASSOC); + $pos = $data['pos']; + if ($newpos < $pos) { + $qs = " + SELECT id,pos + FROM bus_category_bus + WHERE pos < $pos + AND pos >= $newpos + AND catid = $catid + ORDER BY pos"; + if (!$res = $DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs, 0); + } + $counter = ($newpos + 1); + for ($i = 0; $i < $DB->db_numrows($res); $i++) { + $res_data = $DB->db_fetch_array($res, $i, PGSQL_ASSOC); + $res_id = $res_data['id']; + $res_pos = $res_data['pos']; + $qs = " + UPDATE bus_category_bus + SET pos = $counter + WHERE id = $res_id"; + + if (!$DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,0); + } + $counter++; + } + } else { + $qs = " + SELECT pos,id + FROM bus_category_bus + WHERE pos > $pos + AND pos <= $newpos + AND catid = $catid + ORDER BY pos"; + if (!$res = $DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs, 0); + } + $counter = ($pos); + for ($i = 0; $i < $DB->db_numrows($res); $i++) { + $res_data = $DB->db_fetch_array($res, $i, PGSQL_ASSOC); + $res_id = $res_data['id']; + $res_pos = $res_data['pos']; + $qs = " + UPDATE bus_category_bus + SET pos = $counter + WHERE id = $res_id"; + if (!$DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs, 0); + } + $counter++; + } + } + $qs = " + UPDATE bus_category_bus + SET pos = $newpos + WHERE id = $id"; + if (!$DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs, 0); + } + $location = "list_bus.phtml?catid=$catid"; + // cach_Toolbox_paragraphs-$ID + $toolbox->cache->remove('paragraphs-' . $catid, 'Toolbox'); + break;// }}} + + /* + * Update the Paragraph + */ + case "Update":// {{{ + $DB->db_exec("BEGIN WORK"); + if (is_array($_POST['delete'])) { + foreach ($_POST['delete'] as $d_row_id) { + $query = " + SELECT filename + FROM files + WHERE id = ".$d_row_id; + $file_res = $DB->db_exec($query); + $filename = pg_result($file_res, 0, 'filename'); + $query = " + DELETE FROM files + WHERE id = ".$d_row_id; + $DB->db_exec($query); + @unlink(UP_BASE.$filename); + unset($_FILES['file_new']['name']); + // remember files have to be repositioned when there are deleted + // get the position number of file then reposition all the ones with a greater pos + $query = " + UPDATE files SET + pos = pos - 1 + WHERE pos > ".$_POST['filename_poshide'.$d_row_id]." + AND bus_id = ".$_POST['id']; + $DB->db_exec($query); + } + } + if (is_array($_FILES['file_new']['name'])) { + foreach ($_FILES['file_new']['name'] as $fileId => $fileName) { + if ($_FILES['file_new']['name'][$fileId]) { + @unlink(UP_BASE.$_POST['oldfile'][$fileId]); + $update_file_name = GLM_TOOLBOX::file_upload($_FILES['file_new']['tmp_name'][$fileId], $_FILES['file_new']['name'][$fileId], UP_BASE); + $query = " + UPDATE files SET + filename = '$update_file_name' + WHERE id = $fileId;"; + $DB->db_exec($query); + } + } + } + if ($_POST['filename_urltext']) { + foreach ($_POST['filename_urltext'] as $fileId => $fileUrlText) { + $query = " + UPDATE files SET + urltext = '$fileUrlText' + WHERE id = $fileId;"; + $DB->db_exec($query); + } + } + if (is_array($_FILES['file']) && $_FILES['file']['name'] != '') { + $res = $DB->db_exec("select max(pos) as maxpos from files where bus_id = ".$_POST['id']); + $maxpos = pg_result($res, 0, 'maxpos'); + $maxpos = ($maxpos) ? ++$maxpos : 1; + $new_file_name = GLM_TOOLBOX::file_upload($_FILES['file']['tmp_name'], $_FILES['file']['name'], UP_BASE); + $query = " + INSERT INTO files + (filename,bytes,type,urltext,bus_id,pos) + VALUES + ('$new_file_name',".$_FILES['file']['size'].",'".$_FILES['file']['type']."', + '".$_POST['filename']."',".$_POST['id'].",$maxpos);"; + $DB->db_exec($query); + } + $oldcatid = ereg_replace("^:","",$oldcatid); + $oldcatid = split(":",$oldcatid); + if ($category) { + $category = ereg_replace("^:","",$category); + $catid = split(":",$category); + } + $array_counter = 0; + if (is_array($catid)) { + $query = " + SELECT catid,pos + FROM bus_category_bus + WHERE busid = $id"; + $res = $DB->db_exec($query); + $oldpos = pg_result($res,0,'pos'); + while ($row = pg_fetch_array($res)) { + // do this only if ald catid is being removed + if (!in_array($row['catid'],$catid)) { + $query = " + UPDATE bus_category_bus SET + pos = pos - 1 + WHERE catid = ".$row['catid']." + AND pos >= $oldpos"; + $DB->db_exec($query); + $query = " + DELETE FROM bus_category_bus + WHERE catid = ".$row['catid']." + aNd busid = $id"; + $DB->db_exec($query); + } + } + foreach ($catid as $key=>$value) { + // do this only if ald catid is being removed + if (!in_array($value,$oldcatid)) { + $qs = "SELECT count(*) as maxpos + FROM bus_category_bus + WHERE catid = $value"; + if (!$res = $DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,1); + } + $row = $DB->db_fetch_array($res,0,PGSQL_ASSOC); + $pos = ($row['maxpos'] == 0) ? (int)0 : (int)$row['maxpos'] ; + $pos++; + $qs = " + INSERT + INTO bus_category_bus + (busid,catid,pos) + VALUES + ($id,$value,$pos)"; + if (!$DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,1); + } + } + } + } + $fields = array_reverse($fields); + $qs = "UPDATE ".TABLE." SET "; + for ($i=0;$iimageDelete($oldy); + } + } + $delete = ${"delete".$tmpimg}; + if ($delete==1) { + $image_tmp_name = ""; + if ($oldy) { + require_once BASE.'Toolkit/Image/Server.php'; + $imServer = new Toolkit_Image_Server(); + $imServer->imageDelete($oldy); + } + } + $qs .= $fields[$i][name]." = '".$image_tmp_name."'"; + if ($i != $LAST) { + $qs .= ","; + } + } elseif ($fields[$i][type]=="seperator") { + //empty + } elseif ($fields[$i][type]=="file") { + $tmpfile = $fields[$i]['name']; + $file_tmp = $$tmpfile; + $oldy = ${"old".$tmpfile}; + $file_tmp_name = ${$tmpfile."_name"}; + if ($file_tmp == "none" || $file_tmp == "") { + $file_tmp_name = $oldy; + } else { + $file_tmp_name = GLM_TOOLBOX::file_upload($file_tmp,$file_tmp_name,UP_BASE); + } + + $delete = ${"delete".$tmpfile}; + if ($delete==1) { + $file_tmp_name = ""; + @unlink(UP_BASE.$oldy); + } + $qs .= $fields[$i][name]." = '".$file_tmp_name."'"; + if ($i != $LAST) { + $qs .= ","; + } + } elseif ($fields[$i]['type']=="bool") { + $value = ($_REQUEST[$fields[$i]['name']]) ? 't' : 'f'; + $qs .= $fields[$i]['name']." = '$value'"; + if ($i != $LAST) { + $qs .= ","; + } + } elseif ($fields[$i][type]=="static") { + // do nothing + } elseif ($fields[$i][type]=="password") { + if (($password && $password2) && ($password == $password2)) { + $qs .= $fields[$i][name]." = '".$$fields[$i][name]."'"; + if ($i != $LAST) { + $qs .= ","; + } + } + } else { + $qs .= $fields[$i][name]." = '".$$fields[$i][name]."'"; + if ($i != $LAST) { + $qs .= ","; + } + } + } else { + $qs = substr($qs,0,strlen($qs)-1); + $qs .= " WHERE ".$fields[$i][name]." = ".$$fields[$i][name]; + } + } + $fields = array_reverse($fields); + if (!$DB->db_exec($qs)) { + $ERRORS .= pg_errormessage($dbd).$qs; + } + $location = "list_bus.phtml?catid=".$catid[0]."&".SID; + // cach_Toolbox_paragraphs-$ID + $toolbox->cache->remove('paragraphs-' . $oldcatid[0], 'Toolbox'); + $toolbox->cache->remove('paragraphs-' . $catid[0], 'Toolbox'); + $DB->db_exec("COMMIT WORK"); + break;// }}} + + /* + * Insert a new paragraph at last position + 1 + */ + case "Insert":// {{{ + if (is_array($_FILES['file']) && $_FILES['file']['name'] != '') { + $new_file_name = GLM_TOOLBOX::file_upload($_FILES['file']['tmp_name'], $_FILES['file']['name'], UP_BASE); + } + if ($category) { + $category = ereg_replace("^:", "", $category); + $catid = split(":", $category); + } + $tmp = ""; + $tmp_value = ""; + for ($i = 0; $i < count($fields); $i++) { + if ($fields[$i]['name'] != ID) { + if ($fields[$i]['type']!="static" && $fields[$i]['type']!="seperator") { + $tmp .= $fields[$i]['name']; + $tmp .= ","; + } + } + } + for ($i=0;$idb_exec("BEGIN WORK")) { + die(pg_errormessage($dbd).$qs); + } + if ($tmp_blank || $_FILES['file']['name']) { + $qs = " + INSERT INTO ".TABLE." + (".ID.", $tmp) + VALUES + (nextval('".SEQUENCE."'), $tmp_value)"; + if (!$res = $DB->db_exec($qs)) { + die(pg_errormessage($dbd).$qs); + } + if ($new_file_name) { + $query = " + INSERT INTO files + (filename,bytes,type,urltext,bus_id) + VALUES + ('$new_file_name',".$_FILES['file']['size'].",'".$_FILES['file']['type']."', + '".$_POST['filename']."',currval('bus_id_seq'));"; + $DB->db_exec($query); + } + if (is_array($catid)) { + foreach ($catid as $key => $value) { + $qs = " + SELECT count(*) as maxpos + FROM bus_category_bus + WHERE catid = $value"; + if (!$res = $DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs, 1); + } + $row2 = $DB->db_fetch_array($res, 0, PGSQL_ASSOC); + if (!$pos = $row2[maxpos]) { + $pos = 1; + } else { + $pos++; + } + $qs = " + INSERT + INTO bus_category_bus + (busid,catid,pos) + VALUES + (currval('bus_id_seq'),$value,$pos)"; + if (!$DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs, 1); + } + } + if (!$res = $DB->db_exec("COMMIT WORK")) { + die(pg_errormessage($dbd).$qs); + } + } else { + $qs = " + SELECT count(*) as maxpos + FROM bus_category_bus + WHERE catid = $catid"; + if (!$res = $DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs, 1); + } + $row2 = $DB->db_fetch_array($res, 0, PGSQL_ASSOC); + if (!$pos = $row2[maxpos]) { + $pos = 1; + } else { + $pos++; + } + $qs = " + INSERT + INTO bus_category_bus + (busid,catid,pos) + VALUES + ($row[id],$catid,$pos)"; + + if (!$DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs, 1); + } + if (!$res = $DB->db_exec("COMMIT WORK")) { + die(pg_errormessage($dbd).$qs); + } + } + } + $location = "list_bus.phtml?catid=".$catid[0]."&".SID; + // cach_Toolbox_paragraphs-$ID + $toolbox->cache->remove('paragraphs-' . $catid[0], 'Toolbox'); + break;// }}} + + /* + * Delete a paragraph + * reposition all other paragraphs + * delete images and files for this + * paragraph + */ + case "Delete":// {{{ + $oldcatid = ereg_replace("^:", "", $oldcatid); + $oldcatid = split(":", $oldcatid); + require_once BASE.'Toolkit/Image/Server.php'; + $imServer = new Toolkit_Image_Server(); + if ($oldimage) { + $imServer->imageDelete($oldimage); + } + if ($oldimage2) { + $imServer->imageDelete($oldimage2); + } + if ($oldimage3) { + $imServer->imageDelete($oldimage3); + } + $query = " + SELECT * + FROM files + WHERE bus_id = $id;"; + if ($fRes = $DB->db_exec($query)) { + while ($fRow = pg_fetch_array($fRes)) { + if (is_file(UP_BASE.$fRow['filename'])) { + unlink(UP_BASE.$fRow['filename']); + } + } + } + foreach ($oldcatid as $key=>$value) { + if ($value) { + $qs = " + SELECT id,pos + FROM bus_category_bus + WHERE busid = $id + AND catid = $value"; + if (!$res = $DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs, 1); + } + $row = $DB->db_fetch_array($res, 0, PGSQL_ASSOC); + $qs = " + SELECT id + FROM bus_category_bus + WHERE pos > $row[pos] + AND catid = $value + ORDER BY pos"; + if (!$res2 = $DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs, 1); + } + $counter = $row[pos]; + for ($i = 0; $i < $DB->db_numrows($res2); $i++) { + $row2 = $DB->db_fetch_array($res2, $i, PGSQL_ASSOC); + + $qs = " + UPDATE bus_category_bus + SET pos = $counter + WHERE id = $row2[id]"; + + if (!$DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs, 1); + } + $counter++; + } + } + } + $qs = " + DELETE FROM bus + WHERE id = $id"; + if (!$DB->db_auto_exec($qs)) { + GLM_TOOLBOX::html_error("failed ->".$qs, 1); + } + $location = "list_bus.phtml?catid=".$oldcatid[0]."&".SID; + // cach_Toolbox_paragraphs-$ID + $toolbox->cache->remove('paragraphs-' . $oldcatid[0], 'Toolbox'); + break;// }}} + + /* + * Cancel Paragraph edit + */ + case "Cancel":// {{{ + $oldcatid = ereg_replace("^:","",$oldcatid); + $oldcatid = split(":",$oldcatid); + $catid = ereg_replace("^:","",$oldcatid); + $catid = split(":",$oldcatid); + $location = "list_bus.phtml?catid=".$oldcatid[0]."&".SID; + break;// }}} + + default:// {{{ + GLM_TOOLBOX::html_error("incorrect value for Command",1); + break;// }}} + + } +} +/* + * Redirect to the list paragraph page + */ +header("Location: $location"); +?> diff --git a/admin/Toolbox/update_bus_category.phtml b/admin/Toolbox/update_bus_category.phtml new file mode 100755 index 0000000..be87eb5 --- /dev/null +++ b/admin/Toolbox/update_bus_category.phtml @@ -0,0 +1,315 @@ +db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,0); + } + $data = $DB->db_fetch_array($result,0,PGSQL_ASSOC); + $pos = $data['pos']; + if ($newpos < $pos) { + $qs = " + SELECT id,pos + FROM bus_category + WHERE pos < $pos + AND pos >= $newpos + AND parent = $parent + ORDER BY pos"; + if (!$res = $DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,0); + } + $counter = ($newpos + 1); + for ($i=0;$i<$DB->db_numrows($res);$i++) { + $res_data = $DB->db_fetch_array($res,$i,PGSQL_ASSOC); + $res_id = $res_data['id']; + $res_pos = $res_data['pos']; + $qs = " + UPDATE bus_category + SET pos = $counter + WHERE id = $res_id"; + if (!$DB->db_exec($qs)) + { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,0); + } + $counter++; + } + } else { + $qs = " + SELECT pos,id + FROM bus_category + WHERE pos > $pos + AND pos <= $newpos + AND parent = $parent + ORDER BY pos"; + if (!$res = $DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,0); + } + $counter = ($pos); + for ($i=0;$i<$DB->db_numrows($res);$i++) { + $res_data = $DB->db_fetch_array($res,$i,PGSQL_ASSOC); + $res_id = $res_data['id']; + $res_pos = $res_data['pos']; + $qs = " + UPDATE bus_category + SET pos = $counter + WHERE id = $res_id"; + if (!$DB->db_exec($qs)) + { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,0); + } + $counter++; + } + } + $qs = " + UPDATE bus_category + SET pos = $newpos + WHERE id = $id"; + if (!$DB->db_exec($qs)) { + GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,0); + } + $toolbox->cache->clean('Nav'); + break;// }}} + // {{{ case "Update": + + /* + * Update the Page + */ + case "Update": + if ($image != "none" && $image != "") { + require_once BASE.'Toolkit/Image/Server.php'; + $imServer = new Toolkit_Image_Server(); + if ($oldimage) { + $imServer->imageDelete($oldimage); + } + $image_name = GLM_TOOLBOX::process_image('image'); + } else { + $image_name = $oldimage; + } + if ($delete == "1") { + $image_name = ""; + require_once BASE.'Toolkit/Image/Server.php'; + $imServer = new Toolkit_Image_Server(); + $imServer->imageDelete($_REQUEST['oldimage']); + } + if ($parent != $oldparent) { + $qs = " + SELECT MAX(pos) as maxpos + FROM bus_category + WHERE parent = $parent"; + $res = $DB->db_exec($qs); + $row = $DB->db_fetch_array($res,0,PGSQL_ASSOC); + $pos = $row[maxpos]; + $pos++; + $qs = " + SELECT pos,id + FROM bus_category + WHERE parent = $oldparent + AND pos > $oldpos + ORDER BY pos"; + $res2 = $DB->db_exec($qs); + $oldparent_counter = $oldpos; + for ($i=0;$i<$DB->db_numrows($res2);$i++) { + $row2 = $DB->db_fetch_array($res2,$i,PGSQL_ASSOC); + $qs = " + UPDATE bus_category + SET pos = $oldparent_counter + WHERE id = $row2[id]"; + $DB->db_exec($qs); + $oldparent_counter++; + } + } else { + $pos = $oldpos; + } + $template = ($template) ? $template : 1; + $featured = ($featured == 't') ? $featured : 'f'; + $include_member_map = ($include_member_map == 't') ? $include_member_map : 'f'; + $no_search_form = ($no_search_form == 't') ? $no_search_form : 'f'; + $section_links = ($section_links == 't') ? $section_links : 'f'; + $region = (is_numeric($region)) ? $region : 'NULL'; + + //$res2 = $DB->db_exec("BEGIN WORK;"); + $qs = " + UPDATE bus_category SET + category = '$category', + featured = '$featured', + include_member_map = '$include_member_map', + no_search_form = '$no_search_form', + meta_descr = '$meta_descr', + title = '$title', + section_links = '$section_links', + parent = $parent, + pos = $pos, + intro = '$intro', + feature_intro = '$feature_intro', + description = '$description', + image = '$image_name', + imagename = '$imagename', + keyword = '$keyword', + template = $template, + short_url = '$short_url', + region = $region + WHERE id = $id"; + if (!$DB->db_exec($qs)) { + GLM_TOOLBOX::html_error("failed ->".$qs,1); + } + if (defined("MEMBERS_DB") && MEMBERS_DB) { + update_member_bus_cat(&$DB); + } + //$DB->db_exec("COMMIT WORK;"); + break;// }}} + // {{{ case "Insert": + + /* + * Insert a new Page at last position + 1 + */ + case "Insert": + $parent = ($parent) ? $parent : 0; + if ($image != "none" && $image != "") { + $image_name = GLM_TOOLBOX::process_image('image'); + } else { + $image_name = $oldimage; + } + $qs = " + SELECT MAX(pos) as maxpos + FROM bus_category + WHERE parent = $parent"; + $res = $DB->db_exec($qs); + $row = $DB->db_fetch_array($res,0,PGSQL_ASSOC); + $nextpos = $row[maxpos]; + $nextpos++; + $template = ($template) ? $template : 1; + $parent = ($parent) ? $parent : 0; + $featured = ($featured == 't') ? $featured : 'f'; + $no_search_form = ($no_search_form == 't') ? $no_search_form : 'f'; + $include_member_map = ($include_member_map == 't') ? $include_member_map : 'f'; + $section_links = ($section_links == 't') ? $section_links : 'f'; + $region = (is_numeric($region)) ? $region : 'NULL'; + + $res2 = $DB->db_exec("BEGIN WORK;"); + $qs = " + INSERT INTO bus_category + (section_links,include_member_map, no_search_form,featured,feature_intro,template,keyword, + category,parent,intro,description,image,imagename,pos,meta_descr, + short_url,title,region) + VALUES + ('$section_links','$include_member_map','$no_search_form','$featured','$feature_intro',$template,'$keyword', + '$category',$parent,'$intro','$description','$image_name','$imagename',$nextpos,'$meta_descr', + '$short_url','$title',$region)"; + if (!$res1 = $DB->db_exec($qs)) { + GLM_TOOLBOX::html_error("failed ->".$qs,1); + } + if (defined("MEMBERS_DB") && MEMBERS_DB && is_array($_REQUEST['member_cats'])) { + foreach ($_REQUEST['member_cats'] as $memb_catid) { + $query = " + INSERT INTO bus_cat_member + (catid, memb_type) + VALUES + (currval('bus_category_id_seq'), $memb_catid);"; + if (!$DB->db_exec($query)) { + die($query.__LINE__); + } + } + } + $DB->db_exec("COMMIT WORK;"); + $toolbox->cache->clean('Nav'); + break;// }}} + // {{{ case "Delete" + /* + * Delete a Page + * reposition all other Pages + * delete images + * Page + */ + case "Delete": + $DB->db_exec("BEGIN WORK"); + $qs = " + SELECT count(*) as count + FROM bus_category_bus + WHERE catid = $id"; + $res = $DB->db_exec($qs); + $row = $DB->db_fetch_array($res,0,PGSQL_ASSOC); + if ($row['count'] >0) { + GLM_TOOLBOX::html_error("Sorry but you have items in there\n + Delete these records first\n",1); + } + $qs = " + SELECT parent + FROM bus_category + WHERE parent = $id"; + $res = $DB->db_exec($qs); + if ($DB->db_numrows($res) >0) { + GLM_TOOLBOX::html_error("Sorry but you have Categories in there\n + Delete these Categories first\n",1); + } + $qs = " + SELECT pos,id + FROM bus_category + WHERE parent = $oldparent + AND pos > $oldpos + ORDER BY pos"; + $res2 = $DB->db_exec($qs); + $oldparent_counter = $oldpos; + for ($i=0;$i<$DB->db_numrows($res2);$i++) { + $row2 = $DB->db_fetch_array($res2,$i,PGSQL_ASSOC); + $qs = " + UPDATE bus_category + SET pos = $oldparent_counter + WHERE id = $row2[id]"; + $DB->db_exec($qs); + $oldparent_counter++; + } + $qs2 = " + DELETE + FROM bus_category + WHERE id = $id"; + $DB->db_exec($qs2); + if (!$DB->db_auto_exec($qs2)) html_error(DB_ERROR_MSG.$qs2,1); + if ($oldimage) { + require_once BASE.'Toolkit/Image/Server.php'; + $imServer = new Toolkit_Image_Server(); + $imServer->imageDelete($oldimage); + } + $DB->db_exec("COMMIT WORK"); + // remove the cache for this paragraphs + // cach_Toolbox_paragraphs-$ID + $toolbox->cache->remove('paragraphs-' . $id, 'Toolbox'); + $toolbox->cache->clean('Nav'); + break;// }}} + // {{{ case "Cancel": + + /* + * Cancel Page edit + */ + case "Cancel": + break;// }}} + // {{{ default + default: + GLM_TOOLBOX::html_error("incorrect value for Command",1); + break;// }}} + } +} +// remove the cache for this paragraphs +// cach_Toolbox_page-$ID +$toolbox->cache->remove('page-' . $id, 'Toolbox'); +$toolbox->cache->remove('paragraphs-' . $id, 'Toolbox'); +//GLM_TOOLBOX::create_sitemap(); +header("Location: ".BASE_URL."admin/Toolbox/list_bus_category.phtml?".SID); +?> diff --git a/admin/Toolbox/updatetoolset.php b/admin/Toolbox/updatetoolset.php new file mode 100755 index 0000000..7863b18 --- /dev/null +++ b/admin/Toolbox/updatetoolset.php @@ -0,0 +1,32 @@ +db_connect(); + $DB->db_exec( "BEGIN WORK" ); + + echo 'replacing newlines with <br> in bus_category
    '; + $DB->db_exec( "update bus_category set description = replace(description,'\\n','
    ')" ); + echo 'replacing newlines with <br> in bus
    '; + $DB->db_exec( "update bus set description = replace(description,'\\n','
    ')" ); + $DB->db_exec( "update bus set description2 = replace(description2,'\\n','
    ')" ); + $DB->db_exec( "update bus set description3 = replace(description3,'\\n','
    ')" ); + + echo 'replacing newlines with <br> in news
    '; + $DB->db_exec( "update news set description = replace(description,'\\n','
    ')" ); + echo 'replacing newlines with <br> in news_block
    '; + $DB->db_exec( "update news_block set description2 = replace(description2,'\\n','
    ')" ); + + $DB->db_exec( "COMMIT WORK" ); + /** + update media_category set description = replace(description,'http://devsys.gaslightmedia.com/www.upnorth.net/','http://www.upnorth.net/'); + update bus_category set description = replace(description,'http://devsys.gaslightmedia.com/www.upnorth.net/','http://www.upnorth.net/'); + */ +?> diff --git a/admin/Toolbox/upgradefiles2.php b/admin/Toolbox/upgradefiles2.php new file mode 100644 index 0000000..c2cd054 --- /dev/null +++ b/admin/Toolbox/upgradefiles2.php @@ -0,0 +1,31 @@ +db_exec( "BEGIN WORK;" ); +echo '

    BEGIN WORK

    '; +$query = "select id,bus_id from files order by bus_id,filename;"; +echo '

    '.$query.'

    '; +if( $data = $DB->db_auto_get_data( $query ) ) +{ + $bus_id = null; + $pos = 1; + foreach( $data as $row ) + { + if( $row['bus_id'] == $bus_id ) + { + $pos++; + } + else + { + $pos = 1; + $bus_id = $row['bus_id']; + } + $query2 = "update files set pos = $pos where id = ".$row['id'].";"; + echo '

    '.$query2.'

    '; + $DB->db_exec( $query2 ); + } +} +$DB->db_exec( "COMMIT WORK;" ); +echo '

    COMMIT WORK

    '; +?> diff --git a/admin/form.js b/admin/form.js new file mode 100644 index 0000000..0bbabf0 --- /dev/null +++ b/admin/form.js @@ -0,0 +1,42 @@ +function reshow(object) { + artist = object.options[object.selectedIndex].text; + for (var i = document.track.names.length;i > 0;i--) + document.track.names.options[0] = null; + reloading = true; + showlinks(); + document.track.names.options[0].selected = true; + return false; +} + +function load(object) { + alert('Just testing: ' + object.options[object.selectedIndex].value); + //window.location.href = object.options[object.selectedIndex].value; + return false; +} + +function showlinks() { + if (artist == 'Chris Rea') { + opt('cr/one.zip','The Road To Hell'); + opt('cr/two.zip','Let\'s Dance'); + } + + if (artist == 'Annie Lennox') { + opt('al/why.zip','Why'); + opt('al/wobg.zip','Walking on Broken Glass'); + } + + if (artist == 'Dina Carrol') { + opt('dc/track1.zip','Escaping'); + opt('dc/track2.zip','Only Human'); + } +} + +function opt(href,text) { + if (reloading) { + var optionName = new Option(text, href, false, false) + var length = document.track.names.length; + document.track.names.options[length] = optionName; + } + else + document.write('