--- /dev/null
+<?php
+
+/**
+ * EditPage.php
+ *
+ * PHP version 5.2
+ *
+ * @category Toolkit
+ * @package Blocks
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: (0.1)
+ * @link <>
+ */
+
+/**
+ * Toolkit_Blocks_Admin_EditPage
+ *
+ * Handles the Edit page for the Block page
+ *
+ * @category Toolkit
+ * @package Blocks
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @release Release: (0.1)
+ * @link <>
+ */
+class Toolkit_Blocks_Admin_EditPage
+{
+ private $_adminPath;
+ private $_dbh;
+ private $_flexyOptions;
+ private $_template;
+ private $_pageId;
+ private $_routerPath;
+ private $_canCreateOnAnyPage;
+
+ /**
+ * Creates a edit page for blocks
+ *
+ * @param Toolkit_Registry $registry Registry Object
+ */
+ public function __construct(
+ Toolkit_Registry $registry,
+ $pageId = null
+ ) {
+ $config = $registry->appConfig;
+ $this->_dbh = $registry->dbh;
+ $this->_flexyOptions = $GLOBALS['flexyOptions'];
+ $this->_adminPath = $config->application->path;
+ $this->_routerPath
+ = MEDIA_BASE_URL . $config->application->setPath;
+ $this->_flexyOptions['templateDir']
+ = BASE . $config->flexy->options->templateDir;
+ $this->_flexyOptions['compileDir']
+ = BASE . $config->flexy->options->compileDir;
+ $this->_template
+ = $config->flexy->templates->editPage;
+ $this->_pageId = $pageId;
+ $this->_canCreateOnAnyPage = $config->canCreateOnAnyPage;
+ }
+
+ private function _getPageName()
+ {
+ try {
+ $sql = "
+ SELECT navigation_name
+ FROM pages
+ WHERE id = :id";
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':id', $this->_pageId, PDO::PARAM_INT);
+ $stmt->execute();
+ return $stmt->fetchColumn();
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ /**
+ * returns the featured pages table data
+ *
+ * @return array features
+ */
+ public function _getBlocks()
+ {
+ $blocks = array();
+ try {
+ $sql = "
+ SELECT b.*, p.navigation_name
+ FROM blocks b LEFT OUTER JOIN pages p
+ ON (b.page_to = p.id)
+ WHERE page_on = :page
+ ORDER BY pos";
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':page', $this->_pageId, PDO::PARAM_INT);
+ $stmt->execute();
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ if ($row['image']) {
+ $row['imageUrl'] = HEADLINE_THUMB . $row['image'];
+ }
+ $row['deleteUrl']
+ = 'blocks.php?ac=Edit&Command=Delete&blockId=' .
+ $row['id'];
+ $blocks[] = $row;
+ }
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ return $blocks;
+ }
+
+ /**
+ * Returns the string of html used to generate the edit page
+ *
+ * @return string
+ */
+ public function toHtml()
+ {
+ $GLOBALS['bottomScripts'][]
+ = CKEDITOR_JS . '';
+ $GLOBALS['bottomScripts'][]
+ = $this->_routerPath . '/js/editPage.js';
+ if ($_GET['blockId'] && $_REQUEST['Command'] == 'Delete') {
+ $blockId = filter_input(
+ INPUT_GET,
+ 'blockId',
+ FILTER_SANITIZE_NUMBER_INT
+ );
+ if ($blockId) {
+ $block = Toolkit_Blocks_Block::fetchById(
+ $this->_dbh,
+ $blockId
+ );
+ if ($block) {
+ $pageOn = $block->getPageOn();
+ // remove this cache file for the block
+ $cache = new Cache_Lite($GLOBALS['cacheOptions']);
+ $cache->remove($pageOn, 'Block');
+ $block->delete($this->_dbh);
+ }
+ header('Location: blocks.php?ac=Edit&page_on=' . $pageOn);
+ }
+ } else if ($_POST) {
+ if ($_FILES['image']['size'] > 0) {
+ $is = new Toolkit_FileServer_ImageAdapter();
+ $imageUploaded = $is->upload('image');
+ }
+ $pageOn = filter_input(
+ INPUT_POST,
+ 'page_on',
+ FILTER_SANITIZE_NUMBER_INT
+ );
+ $pageTo = filter_input(
+ INPUT_POST,
+ 'page_to',
+ FILTER_SANITIZE_NUMBER_INT
+ );
+ $blockId = filter_input(
+ INPUT_POST,
+ 'blockId',
+ FILTER_SANITIZE_NUMBER_INT
+ );
+ $title = filter_input(
+ INPUT_POST,
+ 'title',
+ FILTER_SANITIZE_STRING
+ );
+ $url = filter_input(
+ INPUT_POST,
+ 'url',
+ FILTER_SANITIZE_STRING
+ );
+ $external = filter_input(
+ INPUT_POST,
+ 'external',
+ FILTER_VALIDATE_BOOLEAN
+ );
+ $description = filter_var(
+ $_REQUEST['description'],
+ FILTER_UNSAFE_RAW
+ );
+ if (get_magic_quotes_gpc()) {
+ $description = stripslashes($description);
+ }
+ $pos = filter_input(
+ INPUT_POST,
+ 'pos',
+ FILTER_SANITIZE_NUMBER_INT
+ );
+ $oldImage = filter_input(
+ INPUT_POST,
+ 'oldImage',
+ FILTER_SANITIZE_STRING
+ );
+
+ $values = array(
+ 'title' => $title,
+ 'description' => $description,
+ 'image' => (($imageUploaded['name'])
+ ? $imageUploaded['name']
+ :$oldImage),
+ 'pageOn' => $pageOn,
+ 'pageTo' => $pageTo,
+ 'url' => Toolkit_Common::filterURI($url),
+ 'external' => $external
+ );
+ if ($blockId) {
+ $values['id'] = $blockId;
+ $oldBlock = Toolkit_Blocks_Block::fetchById
+ ($this->_dbh,
+ $blockId
+ );
+ if ($oldBlock) {
+ $values['pos'] = $oldBlock->getPos();
+ $pageOn = $oldBlock->getPageOn();
+ // remove this cache file for the oldblock
+ $cache = new Cache_Lite($GLOBALS['cacheOptions']);
+ $cache->remove($pageOn, 'Block');
+ }
+ }
+ $block = Toolkit_Blocks_Block::createByValues(
+ $values
+ );
+ if ($block) {
+ $pageOn = $block->getPageOn();
+ // remove this cache file for the block
+ $cache = new Cache_Lite($GLOBALS['cacheOptions']);
+ $cache->remove($pageOn, 'Block');
+ $block->save($this->_dbh);
+ }
+ header('Location: blocks.php?ac=Edit&page_on=' . $pageOn);
+ return false;
+ } else {
+ $tpl = new HTML_Template_Flexy($this->_flexyOptions);
+ $tpl->compile($this->_template);
+
+ $page = new stdClass();
+ if (is_numeric($this->_pageId)) {
+ $page->pageName = $this->_getPageName();
+ }
+ $page->baseUrl = MEDIA_BASE_URL;
+ $page->pageOn = $this->_pageId;
+ $page->blocks
+ = ($this->_pageId)
+ ? $this->_getBlocks()
+ : false;
+ $page->canCreateOnAnyPage = $this->_canCreateOnAnyPage;
+ return $tpl->bufferedOutputObject($page);
+ }
+ }
+}
+
--- /dev/null
+<?php
+
+/**
+ * ListFeatures.php
+ *
+ * PHP version 5.2
+ *
+ * @category Toolkit
+ * @package Blocks
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: (0.1)
+ * @link <>
+ */
+
+/**
+ * Toolkit_Tags_Admin_ListFeatures
+ *
+ * Handles the listing of the Pages that have the blocks on them.
+ *
+ * @category Toolkit
+ * @package Blocks
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @release Release: (0.1)
+ * @link <>
+ */
+class Toolkit_Blocks_Admin_ListPages
+{
+ private $_adminPath;
+ private $_dbh;
+ private $_flexyOptions;
+ private $_template;
+ private $_routerPath;
+
+ /**
+ * Creates a list of the featured pages
+ *
+ * @param Toolkit_Registry $registry Registry Object
+ */
+ public function __construct(Toolkit_Registry $registry)
+ {
+ $config = $registry->appConfig;
+ $this->_dbh = $registry->dbh;
+ $this->_flexyOptions = $GLOBALS['flexyOptions'];
+ $this->_adminPath = $config->application->path;
+ $this->_routerPath
+ = MEDIA_BASE_URL . $config->application->setPath;
+ $this->_flexyOptions['templateDir']
+ = BASE . $config->flexy->options->templateDir;
+ $this->_flexyOptions['compileDir']
+ = BASE . $config->flexy->options->compileDir;
+ $this->_template
+ = $config->flexy->templates->listPages;
+ }
+
+ /**
+ * returns the featured pages table data
+ *
+ * @return array features
+ */
+ private function _getPages()
+ {
+ $breadCrumbsFactory = new Toolkit_BreadCrumbsFactory(
+ new Toolkit_Toolbox_PageGatewayPublishFactory(
+ $this->_dbh
+ )
+ );
+ $breadCrumbHelper = $breadCrumbsFactory->createBreadCrumbsHelper();
+ $pages = array();
+ try {
+ $sql = "
+ SELECT count(b.id) as count,b.page_on,p.navigation_name
+ FROM blocks.blocks b
+ LEFT OUTER JOIN pages p ON (b.page_on = p.id)
+ GROUP BY navigation_name,page_on";
+ $stmt = $this->_dbh->query($sql);
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $row['editUrl']
+ = $this->_adminPath . '?ac=Edit&page_on=' .
+ $row['page_on'];
+ $row['breadCrumbs']
+ = $breadCrumbHelper->toHtml($row['page_on']);
+ $row['pageUrl'] = Toolkit_Template_Page::getSeoUrl(
+ new Toolkit_Toolbox_PageGatewayPublish($this->_dbh),
+ $row['page_on']
+ );
+ $row['deleteUrl']
+ = 'blocks.php?Command=Delete&pageId=' .
+ $row['page_on'];
+ $pages[$row['page_on']] = $row;
+ }
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ return $pages;
+ }
+
+ /**
+ * Returns the string of html used to generate the list of Pages.
+ *
+ * @return string
+ */
+ public function toHtml()
+ {
+ if ($_REQUEST['Command'] == 'Delete') {
+ $pageId = filter_input(
+ INPUT_GET,
+ 'pageId',
+ FILTER_SANITIZE_NUMBER_INT
+ );
+ if ($pageId) {
+ try {
+ $sql = "
+ DELETE
+ FROM blocks
+ WHERE page_on = :page_on";
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':page_on', $pageId, PDO::PARAM_INT);
+ $stmt->execute();
+ } catch(PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+ }
+ $GLOBALS['bottomScripts'][]
+ = $this->_routerPath . '/js/listPages.js';
+ $tpl = new HTML_Template_Flexy($this->_flexyOptions);
+ $tpl->compile($this->_template);
+
+ $page = new stdClass();
+ $page->baseUrl = MEDIA_BASE_URL;
+ $page->addUrl = $this->_adminPath . '?ac=Edit';
+ $page->pages = $this->_getPages();
+
+ return $tpl->bufferedOutputObject($page);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * PageTree.php
+ *
+ * PHP version 5.2
+ *
+ * @category Toolkit
+ * @package Blocks
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: (0.1)
+ * @link <>
+ */
+
+/**
+ * Toolkit_Package_PageTree
+ *
+ * Display the toolbox page as ul lil list for jQuery-Column viewer
+ *
+ * @category Toolkit
+ * @package Blocks
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @release Release: (0.1)
+ * @link <>
+ */
+class Toolkit_Blocks_Admin_PageTree
+{
+ private $_dbh;
+ private $_rootNodeStart = "<ul class=\"menu\" id=\"demo1\">\n";
+ private $_leafStartExpanded = "\n\t<li class=\"expanded\" %s>\n";
+ private $_leafStartLeaf = "\n\t<li class=\"leaf\" %s>\n";
+ private $_subTreeStart = "\n<ul class=\"menu\">\n";
+ private $_treeEnd = "\n</ul>\n";
+ private $_leafEnd = "\n\t</li>\n";
+ private $_tree;
+
+ public function __construct(PDO $dbh)
+ {
+ $this->_dbh = $dbh;
+ }
+
+ /**
+ * creates and executes the sql query for getting the pages
+ *
+ * @return array | null
+ */
+ private function _findAll()
+ {
+ try {
+ if (defined('MEMBERS_CATEGORY') && MEMBERS_CATEGORY) {
+ $sql = "
+ SELECT id,parent,navigation_name
+ FROM pages
+ WHERE id NOT IN (".MEMBERS_CATEGORY.")
+ AND parent NOT IN (".MEMBERS_CATEGORY.")
+ ORDER by parent, pos";
+ } else {
+ $sql = "
+ SELECT id,parent,navigation_name
+ FROM pages
+ ORDER by parent, pos";
+ }
+
+
+ return $this->_dbh
+ ->query($sql)
+ ->fetchAll(PDO::FETCH_ASSOC);
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ /**
+ * Get all pages for the tree
+ *
+ * @return array
+ */
+ private function _fetchPages()
+ {
+ $pages = $this->_findAll();
+ if (is_array($pages)) {
+ $threads = array();
+ foreach ($pages as $page) {
+ $page['children'] = array();
+ $threads[] = $page;
+ }
+
+ $children = array();
+ while (list($key, $value) = each ($threads)) {
+ $children[$value['parent']][$value['id']] = $value;
+ }
+
+ $this->_tree = $children;
+ } else {
+ $this->_tree = array();
+ }
+ }
+
+ /**
+ * Create html of the pages tree for jqueyr.columnview
+ *
+ * @return string
+ */
+ public function toHtml()
+ {
+ $this->_fetchPages();
+ if (is_array($this->_tree)) {
+ $html = $this->createTree($this->_tree, reset($this->_tree));
+ }
+ return $html;
+ }
+
+ /**
+ * Creates the tree structure for the pages jquery column view
+ *
+ * @param array $tree Array for tree
+ * @param type $leaf Array for leaf
+ * @param type $level tree level
+ *
+ * @return string
+ */
+ protected function createTree(array $tree, $leaf, $level = 0)
+ {
+ $html = !$level ? $this->_rootNodeStart : $this->_subTreeStart;
+ if (is_array($leaf) && !empty($leaf)) {
+ while (list($parent, $branch) = each($leaf)) {
+ if ($tree[$parent]) {
+ $html .= sprintf($this->_leafStartExpanded, null);
+ $html .= "<a href=\"#\" rel=\"{$branch['id']}\">{$branch['navigation_name']} </a> ";
+ $html .= $this->createTree($tree, $tree[$parent], $level + 1);
+ } else {
+ $html .= sprintf($this->_leafStartLeaf, null);
+ $html .= "<a href=\"#\" rel=\"{$branch['id']}\">{$branch['navigation_name']} </a> ";
+ $html .= $this->_leafEnd;
+ }
+ }
+ }
+ $html .= $this->_treeEnd;
+ if ($level) {
+ $html .= $this->_leafEnd;
+ }
+ return $html;
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Block.php
+ *
+ * PHP version 5.2
+ *
+ * @category Toolkit
+ * @package Blocks
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: (0.1)
+ * @link <>
+ */
+
+/**
+ * Toolkit_Package_Block
+ *
+ * Class constructs an object for the Block table of the GLM BLock
+ * Application. Handles the insert and update by way of the save method.
+ *
+ * @category Toolkit
+ * @package Blocks
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @release Release: (0.1)
+ * @link <>
+ */
+class Toolkit_Blocks_Block
+{
+ protected $tableName = "blocks";
+ protected $primaryKey = "id";
+ private $_id;
+ private $_title;
+ private $_description;
+ private $_image;
+ private $_pageOn;
+ private $_pageTo;
+ private $_url;
+ private $_external;
+ private $_pos;
+
+ /**
+ * Creates objects of type Block
+ *
+ * @param array $values values to use for the Block
+ */
+ public function __construct($values)
+ {
+ extract($values);
+ $this->setTitle($title)
+ ->setImage($image)
+ ->setDescription($description)
+ ->setPageOn($pageOn)
+ ->setPageTo($pageTo)
+ ->setPos($pos)
+ ->setUrl($url)
+ ->setExternal($external);
+ if ($id) {
+ $this->setId($id);
+ }
+ }
+
+ /**
+ * Static method to create Block objects from an array of values
+ *
+ * @param array $values values to create block with
+ *
+ * @return Toolkit_Blocks_Block
+ */
+ public static function createByValues($values)
+ {
+ return new Toolkit_Blocks_Block($values);
+ }
+
+ /**
+ * Fetch a block by id if not found return false
+ *
+ * @param PDO $dbh Database Connection
+ * @param type $id id of block to fetch
+ *
+ * @return false | Toolkit_Blocks_Block
+ */
+ public static function fetchById(PDO $dbh, $id)
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM blocks
+ WHERE id = :id";
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(':id', $id, PDO::PARAM_INT);
+ $stmt->execute();
+ $values = $stmt->fetch(PDO::FETCH_ASSOC);
+ if ($values) {
+ $values['pageOn'] = $values['page_on'];
+ $values['pageTo'] = $values['page_to'];
+ return Toolkit_Blocks_Block::createByValues($values);
+ } else {
+ return false;
+ }
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ /**
+ * Fetch a block by id if not found return false
+ *
+ * @param PDO $dbh Database Connection
+ * @param type $pageOn id of block to fetch
+ *
+ * @return false | Toolkit_Blocks_Block
+ */
+ public static function fetchByPageOn(PDO $dbh, $pageOn)
+ {
+ $blocks = array();
+ try {
+ $sql = "
+ SELECT *
+ FROM blocks
+ WHERE page_on = :id
+ ORDER BY pos";
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(':id', $pageOn, PDO::PARAM_INT);
+ $stmt->execute();
+ while ($values = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $values['pageOn'] = $values['page_on'];
+ $values['pageTo'] = $values['page_to'];
+ $blocks[] = Toolkit_Blocks_Block::createByValues($values);
+ }
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ return $blocks;
+ }
+
+ /**
+ * Returns the Blocks id
+ *
+ * @return id
+ */
+ public function getId()
+ {
+ return $this->_id;
+ }
+
+ /**
+ * Sets the Blocks id
+ *
+ * @param type $id Id to set (must be numeric)
+ *
+ * @return Toolkit_Blocks_Block
+ * @throws Exception
+ */
+ public function setId($id)
+ {
+ if (!is_numeric($id)) {
+ throw new Exception('id must be an integer');
+ }
+ if (!$this->_id) {
+ $this->_id = $id;
+ }
+ return $this;
+ }
+
+ /**
+ * Returns Blocks title
+ *
+ * @return title
+ */
+ public function getTitle()
+ {
+ return $this->_title;
+ }
+
+ /**
+ * Sets the Blocks title
+ *
+ * @param string $title Title to set for Block
+ *
+ * @return Toolkit_Blocks_Block
+ */
+ public function setTitle($title)
+ {
+ $this->_title = $title;
+ return $this;
+ }
+
+ /**
+ * Returns Blocks url
+ *
+ * @return url
+ */
+ public function getUrl()
+ {
+ return $this->_url;
+ }
+
+ /**
+ * Sets the Blocks url
+ *
+ * @param string $url Url to set for Block
+ *
+ * @return Toolkit_Blocks_Block
+ */
+ public function setUrl($url)
+ {
+ $this->_url = $url;
+ return $this;
+ }
+
+ /**
+ * Returns if External
+ *
+ * @return external
+ */
+ public function getExternal()
+ {
+ return $this->_external;
+ }
+
+ /**
+ * Sets if Url is external
+ *
+ * @param string $external Boolean if external url
+ *
+ * @return Toolkit_Blocks_Block
+ */
+ public function setExternal($external)
+ {
+ $this->_external = $external;
+ return $this;
+ }
+
+ /**
+ * Returns the Blocks description
+ *
+ * @return description
+ */
+ public function getDescription()
+ {
+ return $this->_description;
+ }
+
+ /**
+ * Sets the Blocks desciption
+ *
+ * @param type $description The description for Block
+ *
+ * @return Toolkit_Blocks_Block
+ */
+ public function setDescription($description)
+ {
+ $this->_description = $description;
+ return $this;
+ }
+
+ /**
+ * Returns the Blocks image
+ *
+ * @return image
+ */
+ public function getImage()
+ {
+ return $this->_image;
+ }
+
+ /**
+ * Sets the Blocks image
+ *
+ * @param string $image
+ *
+ * @return Toolkit_Blocks_Block
+ */
+ public function setImage($image)
+ {
+ $this->_image = $image;
+ return $this;
+ }
+
+ /**
+ * Returns the Blocks Page id to display the block on
+ *
+ * @return page_on
+ */
+ public function getPageOn()
+ {
+ return $this->_pageOn;
+ }
+
+ /**
+ * Sets the Blocks page on
+ *
+ * @param type $pageOn The page to display the Block on
+ *
+ * @return Toolkit_Blocks_Block
+ */
+ public function setPageOn($pageOn)
+ {
+ $this->_pageOn = $pageOn;
+ return $this;
+ }
+
+ /**
+ * Returns the Page To display Block on
+ *
+ * @return page_to
+ */
+ public function getPageTo()
+ {
+ return $this->_pageTo;
+ }
+
+ /**
+ * Sets the Page to display the Block on
+ *
+ * @param type $pageTo The page id to display the Block on
+ *
+ * @return Toolkit_Blocks_Block
+ */
+ public function setPageTo($pageTo)
+ {
+ $this->_pageTo = $pageTo;
+ return $this;
+ }
+
+ /**
+ * Return the Blocks position on the page
+ *
+ * @return pos
+ */
+ public function getPos()
+ {
+ return $this->_pos;
+ }
+
+ /**
+ * Sets the Position of the Block
+ *
+ * @param type $pos Position of the Block on the Page
+ *
+ * @return Toolkit_Blocks_Block
+ */
+ public function setPos($pos)
+ {
+ $this->_pos = $pos;
+ return $this;
+ }
+
+ /**
+ * Checks the id of the object if it is set then calls update othervise
+ * calls insert function
+ *
+ * @param PDO $dbh Database connection
+ * @param boolean $saveNullFields To save nul fields or not
+ *
+ * @return viod
+ */
+ public function save(PDO $dbh)
+ {
+ if ($this->_id) {
+ $this->update($dbh);
+ } else {
+ $this->insert($dbh);
+ }
+ }
+
+ /**
+ * Inserts the object into the $this->tableName and returns the object
+ * being created
+ *
+ * @param PDO $dbh Database Connection
+ *
+ * @return Toolkit_Blocks_Block
+ */
+ public function insert(PDO $dbh)
+ {
+ try {
+ $methods = get_class_methods(get_class($this));
+ $values = array();
+ if ($methods) {
+ $pattern = '/get(.*)/';
+ foreach ($methods as $mName) {
+ if (preg_match($pattern, $mName, $matches)) {
+ $func = create_function(
+ '$c',
+ 'return "_" . strtolower($c[1]);'
+ );
+ $fieldName = preg_replace_callback(
+ '/([A-Z])/',
+ $func,
+ $matches[1]
+ );
+ $fieldName = preg_replace('/^_/', '', $fieldName);
+ $values[$fieldName] = $this->$matches[0]();
+ }
+ }
+ }
+ $defaultVars = get_class_vars(get_class($this));
+ $primaryKey = $defaultVars['primaryKey'];
+ $tableName = $defaultVars['tableName'];
+ unset($values[$primaryKey]);
+ // get the position for this insert
+ $values['pos'] = $this->_returnNextPos($dbh, $values['page_on']);
+ $sql = Toolkit_Common::createSQLInsert(
+ $tableName,
+ array_keys($values)
+ );
+ $sql .= " RETURNING $primaryKey";
+ $stmt = Toolkit_Common::prepareQuery(
+ $dbh,
+ $tableName,
+ $sql,
+ $values
+ );
+ $stmt->execute();
+ $setter = 'set'.ucfirst($primaryKey);
+ $this->$setter($stmt->fetchColumn());
+ return $this;
+ } catch(PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ /**
+ * returs the next positition for the given page_on
+ *
+ * @param PDO $dbh Database Connection
+ * @param int $pageOn page to display block on
+ *
+ * @return int
+ */
+ private function _returnNextPos(PDO $dbh, $pageOn)
+ {
+ try {
+ $sql = "
+ SELECT count(id)
+ FROM blocks
+ WHERE page_on = :page_on";
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(':page_on', $pageOn, PDO::PARAM_INT);
+ $stmt->execute();
+ $nextPos = $stmt->fetchColumn();
+ return ($nextPos) ? ++$nextPos : 1;
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ /**
+ * Updates the object
+ *
+ * @param PDO $dbh Database Connection
+ *
+ * @return Toolkit_Blocks_Block
+ */
+ public function update(PDO $dbh)
+ {
+ try {
+ $methods = get_class_methods(get_class($this));
+ $values = array();
+ if ($methods) {
+ $pattern = '/get(.*)/';
+ foreach ($methods as $mName) {
+ if (preg_match($pattern, $mName, $matches)) {
+ $func = create_function(
+ '$c',
+ 'return "_" . strtolower($c[1]);'
+ );
+ $fieldName = preg_replace_callback(
+ '/([A-Z])/',
+ $func,
+ $matches[1]
+ );
+ $fieldName = preg_replace('/^_/', '', $fieldName);
+ $fieldValue = $this->$matches[0]();
+ $values[$fieldName] = $fieldValue;
+ }
+ }
+ }
+ $defaultVars = get_class_vars(get_class($this));
+ $primaryKey = $defaultVars['primaryKey'];
+ $tableName = $defaultVars['tableName'];
+ $sql = Toolkit_Common::createSQLUpdate(
+ $tableName,
+ array_keys($values),
+ array("$primaryKey = :$primaryKey")
+ );
+ $stmt = Toolkit_Common::prepareQuery(
+ $dbh,
+ $tableName,
+ $sql,
+ $values
+ );
+ $stmt->execute();
+ return $this;
+ } catch(PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ /**
+ * Removes a object from the database by the id
+ * if id is not set then it throws an error
+ *
+ * @param PDO $dbh
+ */
+ public function delete(PDO $dbh)
+ {
+ if (!$this->getId()) {
+ throw new Exception('id is not set');
+ }
+ try {
+ $sql = "
+ DELETE
+ FROM {$this->tableName}
+ WHERE id = :id";
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(':id', $this->getId(), PDO::PARAM_INT);
+ $stmt->execute();
+ } catch(PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+}
+
--- /dev/null
+--
+-- setup schema
+--
+
+CREATE SCHEMA blocks;
+GRANT ALL ON SCHEMA blocks TO nobody;
+
+--
+-- Tables
+--
+
+\i ./tables/blocks.sql
\ No newline at end of file
--- /dev/null
+--
+-- Drops schema
+-- WARNING: CANNOT BE UNDONE
+--
+
+DROP SCHEMA IF EXISTS blocks CASCADE;
\ No newline at end of file
--- /dev/null
+DROP TABLE IF EXISTS blocks.blocks;
+
+CREATE TABLE blocks.blocks (
+ id SERIAL,
+ title TEXT,
+ description TEXT,
+ image TEXT,
+ url TEXT,
+ external BOOLEAN,
+ page_on INTEGER NOT NULL
+ REFERENCES toolbox.pages(id)
+ ON DELETE CASCADE,
+ page_to INTEGER,
+ pos INTEGER NOT NULL DEFAULT 1,
+ PRIMARY KEY (id)
+);
+
+GRANT ALL ON blocks.blocks TO nobody;
+GRANT ALL ON blocks.blocks_id_seq TO nobody;
\ No newline at end of file
--- /dev/null
+--
+-- Upgrade block to have url and external option
+--
+
+ALTER TABLE blocks.blocks drop CONSTRAINT blocks_page_to_fkey;
+ALTER TABLE blocks.blocks ALTER page_to DROP NOT NULL;
+ALTER TABLE blocks.blocks ADD url TEXT;
+ALTER TABLE blocks.blocks ADD external BOOLEAN;
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Display.php
+ *
+ * PHP version 5.2
+ *
+ * @category Toolkit
+ * @package Blocks
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: (0.1)
+ * @link <>
+ */
+
+/**
+ * Toolkit_Package_Display
+ *
+ * Creates an array
+ *
+ * @category Toolkit
+ * @package Blocks
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @release Release: (0.1)
+ * @link <>
+ */
+class Toolkit_BLocks_Display
+{
+ private $_dbh;
+
+ public function __construct(PDO $dbh)
+ {
+ $this->_dbh = $dbh;
+ }
+
+ public function getPageBlocksAsArray($pageId)
+ {
+ $pageBlocks = array();
+ $blocks = Toolkit_Blocks_Block::fetchByPageOn($this->_dbh, $pageId);
+ if (!empty($blocks)) {
+ foreach ($blocks as $block) {
+ if ($block->getUrl()) {
+ $url = $block->getUrl();
+ } else {
+ $url = Toolkit_Template_Page::getSeoUrl(
+ new Toolkit_Toolbox_PageGatewayPublish($this->_dbh),
+ $block->getPageTo()
+ );
+ }
+ $pageBlocks[] = array(
+ 'external' => $block->getExternal(),
+ 'href' => $url,
+ 'img' => ($block->getImage())
+ ? HEADLINE_THUMB . $block->getImage()
+ : '',
+ 'header' => $block->getTitle(),
+ 'descr' => $block->getDescription()
+ );
+ }
+ }
+ return $pageBlocks;
+ }
+}
+
--- /dev/null
+<?php
+
+/**
+ * IndexController.php
+ *
+ * PHP version 5.2
+ *
+ * @category Toolkit
+ * @package Blocks
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: (0.1)
+ * @link <>
+ */
+
+/**
+ * Toolkit_Tags_IndexController
+ *
+ * Controller for admin side of the Featured pages
+ *
+ * @category Toolkit
+ * @package Blocks
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @release Release: (0.1)
+ * @link <>
+ */
+class Toolkit_Blocks_IndexController
+ extends Toolkit_BaseControllerAbstract
+ implements Toolkit_IController
+{
+
+ public function __construct(Toolkit_Registry $registry)
+ {
+ parent::__construct($registry);
+ $GLOBALS['styleSheets'][] = MEDIA_BASE_URL .
+ $registry->appConfig->application->setPath . '/css/style.css';
+ }
+ /**
+ * default action used
+ *
+ * @return string html
+ */
+ public function indexAction()
+ {
+ $GLOBALS['bottomScripts'][] = MEDIA_BASE_URL .
+ $this->registry->appConfig->application->setPath .
+ '/js/jquery.columnview.js';
+ // look at canCreateOnAnyPage
+ $canCreateOnAnyPage = $this->registry->appConfig->canCreateOnAnyPage;
+ if ($canCreateOnAnyPage) {
+
+ $list = new Toolkit_Blocks_Admin_ListPages($this->registry);
+ $html = $list->toHtml();
+ } else {
+ $edit = new Toolkit_Blocks_Admin_EditPage(
+ $this->registry,
+ HOME_ID
+ );
+ $html = $edit->toHtml();
+ }
+ return $html;
+ }
+
+ /**
+ * Add/Edit Page Action
+ *
+ * @return string html
+ */
+ public function EditAction()
+ {
+ $GLOBALS['bottomScripts'][] = MEDIA_BASE_URL .
+ $this->registry->appConfig->application->setPath .
+ '/js/jquery.columnview.js';
+ $pageId = filter_input(
+ INPUT_GET,
+ 'page_on',
+ FILTER_SANITIZE_NUMBER_INT
+ );
+ $edit = new Toolkit_Blocks_Admin_EditPage(
+ $this->registry,
+ $pageId
+ );
+ return $edit->toHtml();
+ }
+
+ /**
+ * Used to create the page selector Column View
+ * this method will call exit to stop it from creating any more html
+ * from top and fotter methods
+ */
+ public function AddAction()
+ {
+ $pageTree = new Toolkit_Blocks_Admin_PageTree($this->registry->dbh);
+ echo $pageTree->toHtml();
+ exit;
+ }
+
+}
--- /dev/null
+; Production server configuration data
+[production]
+application.name = "GLM Blocks"
+application.path = MEDIA_BASE_URL "admin/blocks.php"
+application.setPath = "Toolkit/Blocks"
+
+; router config
+router.path = BASE "Toolkit/Blocks"
+router.application = "Blocks"
+
+; PEAR HTML_Template_Flexy Options and settings
+flexy.options.templateDir = "Toolkit/Blocks/templates"
+flexy.options.compileDir = "Toolkit/Blocks/templates/compiled"
+flexy.templates.listPages = "listPages.html"
+flexy.templates.editPage = "editPage.html"
+
+; jQuery settings
+jqueryui.version = "1.8.13"
+; jQuery themes {"base", "cupertino", "smoothness", "start"}
+jqueryui.theme = "base"
+
+canCreateOnAnyPage = Off
+
+; development server configuration data inherits from production and
+; overrides values as necessary
+[development : production]
+
+; chuck's server configuration data inherits from development
+; and overrides values as necessary
+[chuck : development]
+
+; john's server configuration data inherits from development
+; and overrides values as necessary
+[john : development]
+
+; steve's server configuration data inherits from development
+; and overrides values as necessary
+[steve : development]
--- /dev/null
+html {
+ font-size: 62.5%;
+ }
+#blocksEditWrapper, #blocksListWrapper {
+ font-size: 12px;
+ font-size: 1.2rem;
+ }
+h2 {
+ font-size: 18px;
+ font-size: 1.8rem;
+ color: #777;
+ }
+.containerobj .widget {
+ background-color: white;
+ }
+.containerobj .active .widget {
+ color: white;
+ background-color: #3671cf;
+ }
+.containerobj .inpath .widget {
+ background-color: #d0d0d0;
+ }
+#demo1 {
+ height: 200px;
+ }
+#demo1 a {
+ padding: 0 3px;
+ }
+.ui-dialog-buttonpane {
+ padding: 0 10px 0 20px !important;
+ }
+#dialog-modal {
+ height: auto !important;
+ }
+.imageBlock {
+ width: 210px;
+ float: left;
+ padding: 0 5px 0 5px;
+}
+.textBlock {
+ float: left;
+ width: 536px;
+ padding: 5px 5px 0 5px;
+}
+.textBlockTextArea {
+ width: 436px;
+ max-width: 436px;
+ min-width: 436px;
+ min-height: 160px;
+ margin: 3px 0 0 0;
+ padding: 3px;
+ font-family: Verdana, Geneva, sans-serif;
+ font-size: 12px;
+ font-size: 1.2rem;
+ border: 1px solid #999;
+}
+#sortable {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+ width: 800px;
+ float: left;
+ overflow: hidden;
+}
+#sortable li {
+ margin: 3px;
+ position: relative;
+ padding: 0 0 3px 25px;
+ overflow: hidden;
+}
+#sortable li span.ui-icon {
+ position: absolute;
+ margin-left: -25px;
+}
+#newBlockForm {
+ float: left;
+ clear: both;
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+ width: 800px;
+ float: left;
+ overflow: hidden;
+}
+#newBlockForm li {
+ margin: 3px;
+ position: relative;
+ padding: 0 0 3px 25px;
+ overflow: hidden;
+}
+#notsortable {
+ list-style-type: none;
+ margin: 10px 0 10px 0;
+ padding: 0;
+ width: 800px;
+ overflow: hidden;
+}
+#notsortable li {
+ overflow: hidden;
+}
+#notsortable li span {
+ margin-left: 20px;
+}
+#blocksListWrapper {
+ width: 800px;
+ border: 1px solid #777;
+ padding: 10px;
+ background: #E1E1E1;
+ }
+#blocksListWrapper h2 {
+ width: 600px;
+ float: left;
+ overflow: hidden;
+ margin: 5px 0 5px 3px;
+ }
+#editPane {
+ float: left;
+ width: 99px;
+ }
+#deletePane {
+ float: right;
+ width: 100px;
+ }
+#mainPane {
+ float: left;
+ width: 500px;
+ overflow: hidden;
+ }
+#infoPane {
+ float: left;
+ display: block;
+ width: 500px;
+ margin: 9px 0 0 8px;
+ border-bottom: 1px solid #B1B1B1;
+ overflow: hidden;
+ font-size: 30px;
+ font-size: 3.0rem;
+ line-height: 28px;
+ color: #777;
+ text-decoration: none;
+ }
+#breadcrumbs {
+ float:left;
+ color: #777;
+ margin: 3px 0 10px 9px;
+ }
+#numberPane {
+ float: right;
+ width: 90px;
+ margin: 20px 0 0 0;
+ }
+a#editBtn, a#deleteBtn {
+ display: block;
+ height: 28px;
+ width: 82px;
+ line-height: 28px;
+ margin: 20px 0 20px 8px;
+ padding: 0 0 0 30px;
+ color: #555;
+ font-family: Verdana, Geneva, sans-serif;
+ text-decoration: none;
+ }
+a#editBtn {
+ background: url(../assets/btn_edit.gif) no-repeat;
+ }
+a#editBtn:hover {
+ color: #09F;
+ background-position: 0px -28px;
+ }
+a#deleteBtn {
+ background: url(../assets/btn_delete.gif) no-repeat;
+ }
+a#deleteBtn:hover {
+ color: #09F;
+ background-position: 0px -28px;
+ }
+#titletext {
+ float: left;
+ display: block;
+ font-size: 30px;
+ font-size: 3.0rem;
+ line-height: 28px;
+ color: #777;
+ text-decoration: none;
+ overflow: hidden;
+ width: 500px;
+ margin: 9px 0 0 8px;
+ border-bottom: 1px solid #B1B1B1;
+ overflow: hidden;
+ font-size: 26px;
+ font-size: 2.6rem;
+ }
+#titletext:hover {
+ color: #09F;
+ }
+#linktext {
+ float: right;
+ padding: 8px 5px 0 0;
+ }
+#numLeft {
+ float: right;
+ display: inline-block;
+ width: 15px;
+ height: 30px;
+ background: url(../assets/left_circle.gif) no-repeat;
+ }
+#numRight {
+ float: right;
+ display: inline-block;
+ width: 15px;
+ height: 30px;
+ background: url(../assets/right_circle.gif) no-repeat;
+ }
+#numMain {
+ float: right;
+ display: inline-block;
+ overflow: hidden;
+ color: #777;
+ font-size: 20px;
+ font-size: 2.0rem;
+ font-weight: bold;
+ line-height: 28px;
+ border-top: 1px solid #B1B1B1;
+ border-bottom: 1px solid #B1B1B1;
+ margin: 0 -3px;
+ }
+a#addPageUrl {
+ display: block;
+ width: 222px;
+ height: 28px;
+ line-height: 28px;
+ padding: 0 0 0 36px;
+ margin: 0 0 10px 0;
+ background: url(../assets/btn_add.gif) no-repeat;
+ color: #555;
+ font-family: Verdana, Geneva, sans-serif;
+ text-decoration: none;
+ }
+a#addPageUrl:hover {
+ color: #09F;
+ background-position: 0px -28px;
+ }
+#blocksEditWrapper {
+ border: 1px solid #777;
+ padding: 10px;
+ margin: 10px 0 0 0;
+ background: #E1E1E1;
+ width: 800px;
+ overflow: hidden;
+ }
+#blocksEditWrapper h2 {
+ width: 600px;
+ float: left;
+ overflow: hidden;
+ margin: 5px 0 5px 3px;
+ }
+#backBtn {
+ display:block;
+ height: 28px;
+ width: 139px;
+ line-height: 28px;
+ margin: 0 3px 0 0;
+ padding: 0 0 0 30px;
+ background: url(../assets/btn_back.gif) no-repeat;
+ color: #555;
+ font-family: Verdana, Geneva, sans-serif;
+ text-decoration: none;
+ }
+#backBtn:hover {
+ color: #09F;
+ background-position: 0px -28px;
+ }
+.title {
+ float: left;
+ display: inline;
+ height: 26px;
+ padding: 0 5px 0 0;
+ margin: 0;
+ }
+.titleLabel {
+ display: inline;
+ font-size: 12px;
+ font-size: 1.2rem;
+ line-height: 26px;
+ margin: 0;
+}
+.urlField {
+ clear: left;
+}
+.editPageTo {
+ display: inline;
+ font-size: 12px;
+ font-size: 1.2rem;
+ line-height: 26px;
+ margin: 0 5px 0 0;
+ }
+#page_to_name {
+ display: inline;
+ font-size: 12px;
+ line-height: 26px;
+ margin: 0 5px 0 0;
+ }
+#addPageTo {
+ display: inline;
+ width: 82px;
+ height: 28px;
+ background: url(../assets/btn_link.gif) no-repeat;
+ border: none;
+ text-align: left;
+ padding: 0 0 0 24px;
+}
+#addPageTo:hover {
+ color: #09F;
+ background-position: 0px -28px;
+ cursor: pointer;
+ }
+#addBtn {
+ display: block;
+ position:absolute;
+ bottom: 5px;
+ right: 5px;
+ width: 82px;
+ height: 28px;
+ background: url(../assets/btn_add_sm.gif) no-repeat;
+ border: none;
+}
+#addBtn:hover {
+ color: #09F;
+ background-position: 0px -28px;
+ cursor: pointer;
+ }
+#updateBtn {
+ display: block;
+ position:absolute;
+ bottom: 5px;
+ right: 5px;
+ width: 82px;
+ height: 28px;
+ background: url(../assets/btn_update.gif) no-repeat;
+ border: none;
+ padding: 0 0px 0 16px;
+ }
+#updateBtn:hover {
+ color: #09F;
+ background-position: 0px -28px;
+ cursor: pointer;
+ }
+#deleteBtn2 {
+ display: block;
+ position:absolute;
+ bottom: 36px;
+ right: 5px;
+ width: 55px;
+ height: 28px;
+ background: url(../assets/btn_delete.gif) no-repeat;
+ border: none;
+ padding: 0 0 0 27px;
+ font-size: 14px;
+ font-size: 1.4rem;
+ line-height: 28px;
+ text-decoration: none;
+ margin: 0px;
+ }
+#deleteBtn2:hover {
+ color: #F00;
+ background-position: 0px -28px;
+ cursor: pointer;
+ }
+.ui-state-highlight {
+ color: #09F;
+ border-color: #09F;
+ background: #09F;
+ }
+.ui-widget-content {
+ margin: 0;
+ padding: 0;
+ }
+.upload {
+ position: relative;
+ width: 210px;
+ height:2 8px;
+ background: url(../assets/btn_upload.gif) no-repeat;
+ line-height: 28px;
+ padding: 0;
+ margin: 5px 0 3px 0;
+ font-size: 12px;
+ font-size: 1.2rem;
+ color: #555;
+ font-family: Verdana, Geneva, sans-serif;
+ text-decoration: none;
+ }
+.upload:hover {
+ color: #09F;
+ background-position: 0px -28px;
+}
+.upload, .image {
+ width: 210px;
+ height: 28px;
+ }
+.image {
+ opacity: 0.01;
+ filter: alpha(opacity=0.01);
+ position: absolute;
+ right: 0px;
+ }
+#upload_text {
+ width: 210px;
+ height: 28px;
+ display: block;
+ cursor: pointer;
+ }
+.upload:hover #upload_text {
+ color: #09F;
+ }
+.file-wrapper {
+ cursor: pointer;
+ display: inline-block;
+ overflow: hidden;
+ position: relative;
+ margin: 5px 0 0 0;
+}
+.file-wrapper input {
+ cursor: pointer;
+ font-size: 100px;
+ height: 100%;
+ filter: alpha(opacity=1);
+ -moz-opacity: 0.01;
+ opacity: 0.01;
+ position: absolute;
+ right: 0;
+ top: 0;
+ width: 210px;
+ height: 28px;
+}
+.file-wrapper .button {
+ width: 180px;
+ height: 28px;
+ background: url(../assets/btn_upload.gif) no-repeat;
+ color: #fff;
+ cursor: pointer;
+ font-size: 12px;
+ font-size: 1.2rem;
+ color: #555;
+ font-family: Verdana, Geneva, sans-serif;
+ text-decoration: none;
+ display: inline-block;
+ line-height: 28px;
+ padding: 0 0 0 30px;
+}
+
+.file-wrapper:hover .button {
+ color: #09F;
+ background-position: 0px -28px;
+ }
+#sideImage {
+ display: block;
+ width: 210px;
+ height: auto;
+}
+.internal_link, .external_link {
+ display: block;
+ float: left;
+ clear: left;
+ overflow: hidden;
+ background: #F5F5F5;
+ border: 1px solid #CCC;
+ width: 290px;
+ margin-top: 5px;
+ padding: 5px;
+}
+.internal_link h3, .external_link h3 {
+ display: block;
+ width: 100%;
+ overflow: hidden;
+ font-size: 14px;
+ font-weight: bold;
+ margin: 0;
+ padding: 0 0 5px 0;
+ color: #777;
+}
+.cke_chrome {
+ float: left;
+ clear: left;
+ margin-top: 5px !important;
+}
--- /dev/null
+$(document).ready(function(){
+ $("#dialog-modal").load('blocks.php?ac=Add', function(){
+ $('#demo1').columnview({
+ preview:false,
+ onchange: function(element) {
+ $("#page_on").text($(element).text());
+ }
+ });
+ });
+});
--- /dev/null
+var SITE = SITE || {};
+
+SITE.fileInputs = function() {
+ var $this = $(this),
+ $val = $this.val(),
+ valArray = $val.split('\\'),
+ newVal = valArray[valArray.length-1],
+ $button = $this.siblings('.button'),
+ $fakeFile = $this.siblings('.file-holder');
+ if(newVal !== '') {
+ $button.text('Image Chosen');
+ if($fakeFile.length === 0) {
+ $button.after('<span class="file-holder">' + newVal + '</span>');
+ } else {
+ $fakeFile.text(newVal);
+ }
+ }
+};
+
+$(function(){
+ $('.file-wrapper input[type=file]').bind('change focus click', SITE.fileInputs);
+
+ $('.deleteBlock > a').click(function(){
+ return confirm('This Delete cannot be undone!\n Are You Sure?');
+ });
+ $('#sortable').live('mousedown', function(e) {
+ e.stopPropagation();
+ });
+ if (CKEDITOR.env.isCompatible) {
+ $("textarea.textBlockTextArea").each(function() {
+ CKEDITOR.replace(
+ $(this).attr('id'),
+ {
+ toolbar : 'LimitedToolset',
+ width : 300,
+ height : 200
+ }
+ );
+ });
+ }
+ $("#sortable").sortable({
+ update: function (event, ui) {
+
+ var url = '../block-pos/?' + $(this).sortable('serialize');
+ $.get(url, function(data){
+ $('.movable').effect('hightlight', {}, 700);
+ });
+ },
+ placeholder: "ui-state-highlight"
+ });
+ //$("#sortable").disableSelection();
+
+ $("#addPageTo").click(function(){
+ $("#dialog-modal").dialog({
+ height: 240,
+ width: 800,
+ modal: true,
+ buttons: {
+ "Select Page": function() {
+ if ($("#page_to").val() != '') {
+ $(this).dialog("close");
+ } else {
+ alert("Select a Page");
+ }
+ },
+ Cancel: function() {
+ $(this).dialog("close");
+ },
+ "Clear Page": function() {
+ $("#page_to_name").text('No Page');
+ $("#page_to").val('');
+ $(this).dialog("close");
+ }
+ }
+ });
+ $("#pages").load('blocks.php?ac=Add', function(){
+ $('#demo1').columnview({
+ preview:false,
+ onchange: function(element) {
+ $("#page_to_name").text($(element).text());
+ $("#page_to").val($(element).attr('rel'));
+ }
+ });
+ });
+ return false;
+ });
+ $(".editPageTo").click(function(){
+ var blockId = $(this).attr('rel');
+ $("#dialog-modal").dialog({
+ height: 240,
+ width: 800,
+ modal: true,
+ buttons: {
+ "Select Page": function() {
+ if ($('[name="page_to"][rel="' + blockId + '"]').val() != '') {
+ $(this).dialog("close");
+ } else {
+ alert("Select a Page");
+ }
+ },
+ Cancel: function() {
+ $(this).dialog("close");
+ },
+ "Clear Page": function() {
+ $('[class="editPageTo"][rel="' + blockId + '"]').text('No Page');
+ $('[name="page_to"][rel="' + blockId + '"]').val('');
+ $(this).dialog("close");
+ }
+ }
+ });
+ $("#pages").load('blocks.php?ac=Add', function(){
+ $('#demo1').columnview({
+ preview:false,
+ onchange: function(element) {
+ $('[class="editPageTo"][rel="' + blockId + '"]').text($(element).text());
+ $('[name="page_to"][rel="' + blockId + '"]').val($(element).attr('rel'));
+ }
+ });
+ });
+ return false;
+ });
+ $(".blockForm").submit(function(){
+ var msg = '';
+ var errors = 0;
+ var title = $('input[name="title"]', this).val();
+ if (title == '') {
+ errors++;
+ msg += "Headline Required\n";
+ }
+ var page_to = $('input[name="page_to"]', this).val();
+ var blockUrl = $('input[name="url"]', this).val();
+ if (page_to == '' && blockUrl == '') {
+ errors++;
+ msg += "Please select a Page to link to\nor Enter a URL!\n";
+ }
+ if (errors > 0) {
+ alert("Error: " + msg);
+ return false;
+ } else {
+ return true;
+ }
+ });
+});
+
+
+
+$(document).ready(function() {
+ $('.file-wrapper input[type=file]').bind('change focus click', SITE.fileInputs);
+});
--- /dev/null
+/**
+ * jquery.columnview-1.2.js
+ *
+ * Created by Chris Yates on 2009-02-26.
+ * http://christianyates.com
+ * Copyright 2009 Christian Yates and ASU Mars Space Flight Facility. All rights reserved.
+ *
+ * Supported under jQuery 1.2.x or later
+ * Keyboard navigation supported under 1.3.x or later
+ *
+ * Dual licensed under MIT and GPL.
+ */
+
+(function($){
+ $.fn.columnview = function(options){
+
+ var settings = $.extend({}, $.fn.columnview.defaults, options);
+
+ // Add stylesheet, but only once
+ if(!$('.containerobj').get(0)){
+ $('head').prepend('\
+ <style type="text/css" media="screen">\
+ .containerobj {\
+ border: 1px solid #ccc;\
+ height:5em;\
+ overflow-x:auto;\
+ overflow-y:hidden;\
+ white-space:nowrap;\
+ position:relative;\
+ }\
+ .containerobj div {\
+ height:100%;\
+ overflow-y:scroll;\
+ overflow-x:hidden;\
+ position:absolute;\
+ }\
+ .containerobj a {\
+ display:block;\
+ white-space:nowrap;\
+ clear:both;\
+ padding-right:15px;\
+ overflow:hidden;\
+ text-decoration:none;\
+ }\
+ .containerobj a:focus {\
+ outline:none;\
+ }\
+ .containerobj a canvas {\
+ }\
+ .containerobj .feature {\
+ min-width:200px;\
+ overflow-y:auto;\
+ }\
+ .containerobj .feature a {\
+ white-space:normal;\
+ }\
+ .containerobj .hasChildMenu {\
+ }\
+ .containerobj .active {\
+ background-color:#3671cf;\
+ color:#fff;\
+ }\
+ .containerobj .inpath {\
+ background-color:#d0d0d0;\
+ color:#000;\
+ }\
+ .containerobj .hasChildMenu .widget {\
+ color:black;\
+ position:absolute;\
+ right:0;\
+ text-decoration:none;\
+ font-size:0.7em;\
+ }\
+ </style>');
+ }
+
+ // Hide original list
+ $(this).hide();
+ // Reset the original list's id
+ var origid = $(this).attr('id');
+ if (origid) {
+ $(this).attr('id', origid + "-processed");
+ }
+
+ // Create new top container from top-level LI tags
+ var top = $(this).children('li');
+ var container = $('<div/>').addClass('containerobj').attr('id', origid).insertAfter(this);
+ var topdiv = $('<div class="top"></div>').appendTo(container);
+ // Set column width
+ if (settings.fixedwidth || $.browser.msie) { // MSIE doesn't support auto-width
+ var width = typeof settings.fixedwidth == "string" ? settings.fixedwidth : '200px';
+ $('.top').width(width);
+ }
+ $.each(top,function(i,item){
+ var topitem = $(':eq(0)',item).clone(true).wrapInner("<span/>").data('sub',$(item).children('ul')).appendTo(topdiv);
+ if (settings.fixedwidth || $.browser.msie)
+ $(topitem).css({'text-overflow':'ellipsis', '-o-text-overflow':'ellipsis','-ms-text-overflow':'ellipsis'});
+ if($(topitem).data('sub').length) {
+ $(topitem).addClass('hasChildMenu');
+ addWidget(container, topitem);
+ }
+ });
+
+ // Firefox doesn't repeat keydown events when the key is held, so we use
+ // keypress with FF/Gecko/Mozilla to enable continuous keyboard scrolling.
+ var key_event = $.browser.mozilla ? 'keypress' : 'keydown';
+
+ // Event handling functions
+ $(container).bind("click " + key_event, function(event){
+ if ($(event.target).is("a,span")) {
+ if ($(event.target).is("span")){
+ var self = $(event.target).parent();
+ }
+ else {
+ var self = event.target;
+ }
+ if (!settings.multi) {
+ delete event.shiftKey;
+ delete event.metaKey;
+ }
+ self.focus();
+ var container = $(self).parents('.containerobj');
+ // Handle clicks
+ if (event.type == "click"){
+ var level = $('div',container).index($(self).parents('div'));
+ var isleafnode = false;
+ // Remove blocks to the right in the tree, and 'deactivate' other
+ // links within the same level, if metakey is not being used
+ $('div:gt('+level+')',container).remove();
+ if (!event.metaKey && !event.shiftKey) {
+ $('div:eq('+level+') a',container).removeClass('active').removeClass('inpath');
+ $('.active',container).addClass('inpath');
+ $('div:lt('+level+') a',container).removeClass('active');
+ }
+ // Select intermediate items when shift clicking
+ // Sorry, only works with jQuery 1.4 due to changes in the .index() function
+ if (event.shiftKey) {
+ var first = $('a.active:first', $(self).parent()).index();
+ var cur = $(self).index();
+ var range = [first,cur].sort(function(a,b){return a - b;});
+ $('div:eq('+level+') a', container).slice(range[0], range[1]).addClass('active');
+ }
+ $(self).addClass('active');
+ if ($(self).data('sub').children('li').length && !event.metaKey) {
+ // Menu has children, so add another submenu
+ var w = false;
+ if (settings.fixedwidth || $.browser.msie)
+ w = typeof settings.fixedwidth == "string" ? settings.fixedwidth : '200px';
+ submenu(container,self,w);
+ }
+ else if (!event.metaKey && !event.shiftKey) {
+ // No children, show title instead (if it exists, or a link)
+ isleafnode = true;
+ var previewcontainer = $('<div/>').addClass('feature').appendTo(container);
+ // Fire preview handler function
+ if ($.isFunction(settings.preview)) {
+ // We're passing the element back to the callback
+ var preview = settings.preview($(self));
+ }
+ // If preview is specifically disabled, do nothing with the previewbox
+ else if (!settings.preview) {
+ }
+ // If no preview function is specificied, use a default behavior
+ else {
+ var title = $('<a/>').attr({href:$(self).attr('href')}).text($(self).attr('title') ? $(self).attr('title') : $(self).text());
+ $(previewcontainer).html(title);
+ }
+ // Set the width
+ var remainingspace = 0;
+ $.each($(container).children('div').slice(0,-1),function(i,item){
+ remainingspace += $(item).width();
+ });
+ var fillwidth = $(container).width() - remainingspace;
+ $(previewcontainer).css({'top':0,'left':remainingspace}).width(fillwidth).show();
+ }
+ // Fire onchange handler function, but only if multi-select is off.
+ // FIXME Need to deal multiple selections.
+ if ($.isFunction(settings.onchange) && !settings.multi) {
+ // We're passing the element back to the callback
+ var onchange = settings.onchange($(self), isleafnode);
+ }
+ }
+ // Handle Keyboard navigation
+ if(event.type == key_event){
+ switch(event.keyCode){
+ case(37): //left
+ $(self).parent().prev().children('.inpath').focus().trigger("click");
+ break;
+ case(38): //up
+ $(self).prev().focus().trigger("click");
+ break;
+ case(39): //right
+ if($(self).hasClass('hasChildMenu')){
+ $(self).parent().next().children('a:first').focus().trigger("click");
+ }
+ break;
+ case(40): //down
+ $(self).next().focus().trigger("click");
+ break;
+ case(13): //enter
+ $(self).trigger("dblclick");
+ break;
+ }
+ }
+ event.preventDefault();
+ }
+ });
+
+ };
+
+ $.fn.columnview.defaults = {
+ multi: false, // Allow multiple selections
+ preview: true, // Handler for preview pane
+ fixedwidth: false,// Use fixed width columns
+ onchange: false // Handler for selection change
+ };
+
+ // Generate deeper level menus
+ function submenu(container,item,width){
+ var leftPos = 0;
+ $.each($(container).children('div'),function(i,mydiv){
+ leftPos += $(mydiv).width();
+ });
+ var submenu = $('<div/>').css({'top':0,'left':leftPos}).appendTo(container);
+ // Set column width
+ if (width)
+ $(submenu).width(width);
+ var subitems = $(item).data('sub').children('li');
+ $.each(subitems,function(i,subitem){
+ var subsubitem = $(':eq(0)',subitem).clone(true).wrapInner("<span/>").data('sub',$(subitem).children('ul')).appendTo(submenu);
+ if (width)
+ $(subsubitem).css({'text-overflow':'ellipsis', '-o-text-overflow':'ellipsis','-ms-text-overflow':'ellipsis'});
+ if($(subsubitem).data('sub').length) {
+ $(subsubitem).addClass('hasChildMenu');
+ addWidget(container, subsubitem);
+ }
+ });
+ }
+
+ // Uses canvas, if available, to draw a triangle to denote that item is a parent
+ function addWidget(container, item, color){
+ var triheight = $(item).height();
+ var canvas = $("<canvas></canvas>").attr({height:triheight,width:10}).addClass('widget').appendTo(item); if(!color){ color = $(canvas).css('color'); }
+ canvas = $(canvas).get(0);
+ if(canvas.getContext){
+ var context = canvas.getContext('2d');
+ context.fillStyle = color;
+ context.beginPath();
+ context.moveTo(3,(triheight/2 - 3));
+ context.lineTo(10,(triheight/2));
+ context.lineTo(3,(triheight/2 + 3));
+ context.fill();
+ } else {
+ /**
+ * Canvas not supported - put something in there anyway that can be
+ * suppressed later if desired. We're using a decimal character here
+ * representing a "black right-pointing pointer" in Windows since IE
+ * is the likely case that doesn't support canvas.
+ */
+ $("<span>►</span>").addClass('widget').css({'height':triheight,'width':10}).prependTo(item);
+ }
+ $(container).find('.widget').bind('click', function(event){
+ event.preventDefault();
+ });
+
+ }
+})(jQuery);
--- /dev/null
+$(document).ready(function(){
+ $('.deleteBlock > a').click(function(){
+ return confirm('This Delete cannot be undone!\n Are You Sure?');
+ });
+ $("#addPageUrl").click(function(){
+ $("#dialog-modal").dialog({
+ height: 240,
+ width: 800,
+ modal: true,
+ buttons: {
+ "Select Page": function() {
+ if ($("#page_on").text() != '') {
+ location.href = "blocks.php?ac=Edit&page_on=" +
+ $("#page_on").text();
+ $(this).dialog("close");
+ } else {
+ alert("Select a Page");
+ }
+ },
+ Cancel: function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+ $("#pages").load('blocks.php?ac=Add', function(){
+ $('#demo1').columnview({
+ preview:false,
+ onchange: function(element) {
+ $("#page_on").text($(element).attr('rel'));
+ }
+ });
+ });
+ return false;
+ });
+});
--- /dev/null
+<?php
+require_once '../../setup.phtml';
+$blocks = $_REQUEST['block'];
+$newPos = 1;
+
+if (is_array($blocks) && !empty($blocks)) {
+ $pageOn = null;
+ $dbh = Toolkit_Database::getInstance();
+ foreach ($blocks as $blockId) {
+ if (is_numeric($blockId)) {
+ $block = Toolkit_Blocks_Block::fetchById($dbh, $blockId);
+ $block->setPos($newPos)->save($dbh);
+ $pageOn = $block->getPageOn();
+ }
+ ++$newPos;
+ }
+ // remove this cache file for the block
+ $cache = new Cache_Lite($GLOBALS['cacheOptions']);
+ $cache->remove($pageOn, 'Block');
+}
+return true;
\ No newline at end of file
--- /dev/null
+{if:canCreateOnAnyPage}
+<a id="backBtn" href="../admin/blocks.php">Back to All Blocks</a>
+{end:}
+<div id="blocksEditWrapper">
+ <h2>Add New {pageName} Block</h2>
+ <ul id="newBlockForm">
+ <li class="ui-widget-content">
+ <form
+ id="newForm"
+ class="blockForm"
+ method="post"
+ action="blocks.php?ac=Edit"
+ enctype="multipart/form-data"
+ flexy:ignore="yes">
+ <input type="hidden" name="page_on" value="{pageOn}">
+ <input type="hidden" id="page_to" name="page_to">
+ <div class="imageBlock">
+ <span class="file-wrapper">
+ <input
+ type="file"
+ name="image"
+ id="image"
+ class="image">
+ <span class="button">Choose Image</span>
+ </span>
+ </div>
+ <div class="textBlock">
+ <input
+ class="title"
+ type="text"
+ name="title"
+ placeholder="Headline">
+ <div class="internal_link">
+ <h3>Internal Link</h3>
+ <label
+ class="titleLabel">Links to:</label>
+ <div id="page_to_name"></div>
+ <button id="addPageTo">Choose</button>
+ </div>
+ <div class="external_link">
+ <h3>External Link</h3>
+ <label
+ class="title">External URL:
+ <input type="checkbox" name="external">
+ </label>
+ <input
+ class="title"
+ type="text"
+ name="url"
+ placeholder="URL">
+ </div>
+ <textarea
+ name="description"
+ id="descr-new"
+ class="textBlockTextArea"></textarea>
+ <input id="addBtn" type="submit" value="Add">
+ </div>
+ </form>
+ </li>
+ </ul>
+ <h2>Edit Current {pageName} Blocks</h2>
+ <div id="dialog-modal" title="Page Selector" style="display:none;">
+ <div id="pages"></div>
+ </div>
+ <ul id="sortable">
+ <li
+ flexy:foreach="blocks,block"
+ id="block_{block[id]}"
+ class="ui-widget-content">
+ <span class="ui-icon ui-icon-arrow-4-diag"></span>
+ <form
+ id="form-{block[id]}"
+ class="blockForm"
+ method="post"
+ action="blocks.php?ac=Edit"
+ enctype="multipart/form-data"
+ flexy:ignore="yes">
+ <input
+ type="hidden"
+ rel="{block[id]}"
+ name="page_on"
+ value="{block[page_on]}">
+ <input
+ type="hidden"
+ rel="{block[id]}"
+ name="page_to"
+ value="{block[page_to]}">
+ <input
+ type="hidden"
+ name="blockId"
+ value="{block[id]}">
+ <input
+ type="hidden" name="oldImage" value="{block[image]}">
+ <div class="imageBlock">
+ <div class="upload">
+ <input type="file" class="image" name="image">
+ <a id="upload_text" class="button">
+ Change Image
+ </a>
+ </div>
+ {if:block[imageUrl]}
+ <img id="sideImage" src="{block[imageUrl]:h}">
+ {end:}
+ </div>
+ <div class="textBlock">
+ <input
+ type="text"
+ class="title"
+ name="title"
+ value="{block[title]}">
+ <div class="internal_link">
+ <h3>Internal Link</h3>
+ <label class="titleLabel">Links to:</label>
+ {if:block[navigation_name]}
+ <a
+ class="editPageTo"
+ rel="{block[id]}"
+ href="#">{block[navigation_name]}</a>
+ {else:}
+ <a
+ class="editPageTo"
+ rel="{block[id]}"
+ href="#">No Page</a>
+ {end:}
+ </div>
+ <div class="external_link">
+ <h3>External Link</h3>
+ <label
+ class="title">External URL:
+ {if:block[external]}
+ <input type="checkbox" name="external" checked>
+ {else:}
+ <input type="checkbox" name="external">
+ {end:}
+ </label>
+ <input
+ class="title"
+ type="text"
+ name="url"
+ placeholder="URL"
+ value="{block[url]}">
+ </div>
+ <textarea
+ name="description"
+ id="descr-{block[id]}"
+ class="textBlockTextArea"
+ style="min-height:{block[imageHeight]}px;">{block[description]}</textarea>
+ <input id="updateBtn" type="submit" value="Update" />
+ <div class="deleteBlock">
+ <a
+ id="deleteBtn2"
+ class=".deleteBlock"
+ href="{block[deleteUrl]:h}"
+ rel="{block[id]}">Delete</a>
+ </div>
+ </div>
+ </form>
+ </li>
+ </ul>
+</div>
--- /dev/null
+<a id="addPageUrl" href="{addUrl:h}">Add GLM Blocks to a Page</a>
+<div id="dialog-modal" title="Page Selector" style="display:none;">
+ <input type="hidden" name="page_on" id="page_on">
+ <div id="pages"></div>
+</div>
+<div id="blocksListWrapper">
+ <h2 class="blockhead">Current Pages with GLM Blocks</h2>
+ <ul flexy:if="pages" id="notsortable">
+ <li flexy:foreach="pages,page" class="ui-widget-content">
+ <div id="editPane">
+ <a id="editBtn" href="{page[editUrl]:h}">Edit</a>
+ </div><!-- /#editPane -->
+ <div id="mainPane">
+ <a id="titletext" target="_blank" href="{page[pageUrl]:h}">{page[navigation_name]}</a>
+ {page[breadCrumbs]:h}
+ </div><!-- /#mainPane -->
+ <div id="deletePane" class="deleteBlock">
+ <a id="deleteBtn" href="{page[deleteUrl]:h}">Delete</a>
+ </div><!-- /#deletePane -->
+ <div id="numberPane">
+ <div id="numRight"></div>
+ <div id="numMain">{page[count]}</div>
+ <div id="numLeft"></div>
+ <div id="linktext">Links:</div>
+ </div><!-- /#numberPane -->
+ </li><!-- /.ui-widget-content -->
+ </ul><!-- /#notsortable -->
+</div><!-- /#blocksListWrapper -->
--- /dev/null
+<?php
+
+/**
+ * EditContact.php
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Contacts
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2010 Gaslight Media
+ * @license Gaslight Media
+ * @version CVS: $Id: EditContact.php,v 1.3 2010/05/13 20:18:38 matrix Exp $
+ * @link http://pear.php.net/package/Contacts
+ * @see References to other sections (if any)...
+ */
+/**
+ * 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);
+
+/**
+ * Description for define
+ */
+define('FORM_ERROR', -1);
+
+/**
+ * Description for define
+ */
+define('NO_RECORD', -2);
+
+/**
+ * Description for define
+ */
+define('INVALID_DB', -3);
+
+/**
+ * Description for define
+ */
+define('MISSING_CONSTANT', -4);
+
+/**
+ * Description for define
+ */
+define('MISSING_CONTACT_TYPE', -5);
+
+/**
+ * Toolkit_Contacts_Admin_EditContact
+ *
+ * Edit Process class to insert or update a contact
+ * can be used with customer table with little modification
+ *
+ * @category Toolkit
+ * @package Contacts
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2010 Steve Sutton
+ * @license Gaslight Media
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Contacts
+ * @see References to other sections (if any)...
+ */
+class Toolkit_Contacts_Admin_EditContact
+ extends Toolkit_FormBuilder implements Toolkit_Form
+{
+ // {{{ properties
+
+ /**
+ * Table in Database which holds the contact data
+ *
+ * @var string
+ * @access public
+ */
+ public $tableName = 'contact';
+
+ /**
+ * Primary Key for the table
+ *
+ * @var string
+ * @access public
+ */
+ public $primaryKey = 'id';
+
+ /**
+ * Sequence for the table
+ *
+ * @var string
+ * @access public
+ */
+ public $sequence = 'contact_id_seq';
+
+ /**
+ * 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();
+
+ /**
+ * The interests from the contact db
+ *
+ * @var array
+ * @access protected
+ */
+ protected $inquiries = array();
+
+ /**
+ * What do you want the error msg to be if the form doesn't validate
+ *
+ * @var string
+ * @access protected
+ */
+ protected $errorMsg
+ = '<div id="form-warning-top">
+ Warning: The form was not sent, please review the errors below.
+ </div>';
+
+ /**
+ * What do you want the success msg to be if the form validates successfully
+ *
+ * @var string
+ * @access protected
+ */
+ protected $successMsg
+ = '<div id="form-success-top">
+ The information below has been successfully submitted.
+ </div>';
+
+ /**
+ * Include a captcha on the form or not
+ *
+ * @var boolean
+ * @access protected
+ */
+ protected $useCaptcha = false;
+
+ /**
+ * 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
+ * <code>
+ * $rules[] = array('element' => 'phone',
+ * 'message' => 'ERROR: Invalid Phone Format!',
+ * 'type' => 'phone',
+ * 'format' => null,
+ * 'validation' => $this->validationType,
+ * 'reset' => true,
+ * 'force' => false);
+ * </code>
+ *
+ * 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.
+ * <code>
+ * $rules[] = array('element' => 'zip',
+ * 'message' => 'ERROR: Invalid Zip!',
+ * 'type' => 'zip',
+ * 'format' => array('requireDBCheck' => true),
+ * 'validation' => $this->validationType,
+ * 'reset' => true,
+ * 'force' => false);
+ * </code>
+ *
+ * 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.
+ * <code>
+ * $rules[] = array('element' => 'state_id',
+ * 'message' => 'ERROR: Invalid State / Province!',
+ * 'type' => 'state',
+ * 'format' => array('requireDBCheck' => true),
+ * 'validation' => $this->validationType,
+ * 'reset' => true,
+ * 'force' => false);
+ * </code>
+ *
+ * @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 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 <form> tag
+ * @param bool $trackSubmit (optional)Whether to track if the form was
+ * submitted by adding a special hidden field
+ *
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @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
+ ) {
+ parent::__construct(
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+
+ $this->dbh = $pdo;
+
+ /**
+ * 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;
+
+ }
+
+ // }}}
+
+ // {{{ checkContactEmail()
+
+ /**
+ * Checks if the member name already exists in the database
+ *
+ * @param array $data The name of the member to check for.
+ *
+ * @return bool False on SQL Query error, otherwise true.
+ * @access protected
+ */
+ public function checkContactEmail($data)
+ {
+ try {
+ // If we're editing a contact, they
+ // can save that member as its
+ // own name. so don't include that
+ // member in the check.
+ if (ctype_digit($_REQUEST[$this->primaryKey])) {
+ $and = "AND {$this->primaryKey} <> :id";
+ }
+ $sql = "
+ SELECT count(*) AS total
+ FROM {$this->tableName}
+ WHERE email = :email
+ $and";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':email', $data, PDO::PARAM_STR);
+ if (ctype_digit($_REQUEST[$this->primaryKey])) {
+ $stmt->bindParam(':id', $_REQUEST[$this->primaryKey], PDO::PARAM_STR);
+ }
+ $stmt->execute();
+ $stmt->bindColumn('total', $valid);
+ $stmt->fetch();
+
+ return !(bool) $valid;
+ } catch (PDOException $e) {
+ return Toolkit_Common::handleError($e);
+ }
+ }
+
+ // }}}
+ // {{{ configureConstats()
+
+ /**
+ * Constant variables for the form
+ *
+ * These values won't get overridden by POST or GET vars
+ *
+ * @return void
+ * @access public
+ */
+ public function configureConstants()
+ {
+ if (ctype_digit($_REQUEST['id'])) {
+ $constants = array('id' => $_REQUEST['id']);
+ } else {
+ $constants = array();
+ }
+ $this->setupConstants($constants);
+ }
+
+ // }}}
+ // {{{ configureDefaults()
+
+ /**
+ * Initializes default form values
+ *
+ * @return void
+ * @access public
+ */
+ public function configureDefaults()
+ {
+ if (ctype_digit($_REQUEST[$this->primaryKey])) {
+ try {
+ $sql = "
+ SELECT ci.id,ig.name
+ FROM contact_inq ci LEFT OUTER JOIN inq_group ig ON (ci.groupid = ig.id)
+ WHERE ci.id = :id";
+ $getIntData = $this->dbh->prepare($sql);
+ $sql = "
+ SELECT *
+ FROM {$this->tableName}
+ WHERE {$this->primaryKey} = :id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(":id", $_REQUEST[$this->primaryKey], PDO::PARAM_INT);
+ $stmt->execute();
+ $defaults = $stmt->fetch(PDO::FETCH_ASSOC);
+ if ($defaults['interest']) {
+ $pattern = "/^:|:$/";
+ $intString = preg_replace($pattern, "", $defaults['interest']);
+ $intArray = explode(":", $intString);
+ if (is_array($intArray) && !empty($intArray)) {
+ $newIntArray = array();
+ foreach ($intArray as $intId) {
+ if (is_numeric($intId)) {
+ $getIntData->bindParam(":id", $intId, PDO::PARAM_INT);
+ $getIntData->execute();
+ $row = $getIntData->fetch(PDO::FETCH_ASSOC);
+ // set the new interest array
+ $newIntArray[$row['name']][$row['id']] = true;
+ }
+ }
+ $defaults['interest'] = $newIntArray;
+ }
+ }
+ if ($defaults['contact_type']) {
+ $pattern = "/^:|:$/";
+ $cTypesString = preg_replace($pattern, "", $defaults['contact_type']);
+ // set the new contact type array
+ $defaults['contact_type'] = explode(":", $cTypesString);
+ }
+ } catch(PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ } else {
+ $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();
+
+ $contactTypesSetup
+ = $this->config->getItem('section', 'contact_types')
+ ->toArray();
+ $cType = $contactTypesSetup['contact_types'];
+ // All Elements are created here. This includes group element definitions.
+ $e[] = array(
+ 'type' => 'hidden',
+ 'name' => 'start',
+ 'display' => $_REQUEST['start']
+ );
+ $e[] = array(
+ 'type' => 'static',
+ 'req' => false,
+ 'name' => 'user_agent',
+ 'display' => 'User Agent'
+ );
+ $e[] = array(
+ 'type' => 'static',
+ 'req' => false,
+ 'name' => 'remote_addr',
+ 'display' => 'Remote Address'
+ );
+ if (ctype_digit($_REQUEST[$this->primaryKey])) {
+ $e[] = array(
+ 'type' => 'hidden',
+ 'req' => false,
+ 'name' => $this->primaryKey
+ );
+ }
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'fname',
+ 'display' => 'First Name'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'lname',
+ 'display' => 'Last Name'
+ );
+ if ($this->tableName == 'customer') {
+ $add1 = 'add1';
+ $add2 = 'add2';
+ } else {
+ $add1 = 'address';
+ $add2 = 'address2';
+ }
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => $add1,
+ 'display' => 'Address 1'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => $add2,
+ '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' => false,
+ 'name' => 'phone',
+ 'display' => 'Phone'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'fax',
+ 'display' => 'Fax'
+ );
+ $e[] = array(
+ 'type' => 'advcheckbox',
+ 'req' => false,
+ 'name' => 'mail_ok',
+ 'display' => 'Mail Ok?',
+ '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' => 'select',
+ 'req' => false,
+ 'name' => 'contact_type',
+ 'display' => 'Contact Type',
+ 'opts' => $cType,
+ 'att' => array('multiple' => 'multiple')
+ );
+ $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' => 'email',
+ 'message' => 'ERROR: Invalid Email Format!',
+ 'type' => 'email',
+ 'format' => array('use_rfc822' => true),
+ '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' => 'email',
+ 'message' => 'ERROR: There is an existing account with this name!',
+ 'type' => 'callback',
+ 'format' => array($this, 'checkContactEmail'),
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ '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);
+ }
+ }
+
+ // }}}
+
+ // {{{ 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 <i>' . $className . '</i> 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 <i>' . $className . '</i> before continuing',
+ MISSING_CONSTANT => 'You have failed to set a CONSTANT for the class <i>' . $className . '</i> to function properly',
+ MISSING_CONTACT_TYPE => 'Please set the property contactType in the class <i>'. $className . '</i> 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 "<div id=\"form-warning-top\">{$message}</div>";
+ }
+
+ // }}}
+
+ // {{{ 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;
+ }
+
+ // }}}
+
+ // {{{ 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);
+ $this->start = $values['start'];
+ unset($values['start']);
+ // 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);
+
+ $isUpdate = (ctype_digit($_REQUEST[$this->primaryKey])) ? true: false;
+
+ 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) . ':';
+ }
+ }
+ if (!isset($values['interest'])) {
+ $values['interest'] = '';
+ }
+ if (is_array($values['contact_type']) && !empty($values['contact_type'])) {
+ $values['contact_type'] = ':' . implode(':', $values['contact_type']) . ':';
+ }
+ if (!isset($values['contact_type'])) {
+ $values['contact_type'] = '';
+ }
+
+ if ($isUpdate) {
+ $this->Action = 'Contact Updated';
+ } else {
+ $this->Action = 'Contact Added';
+ }
+ $values['create_date'] = date('m/d/Y');
+ // build a contact or customer class object with the values from
+ // the Contact form
+ if ($this->tableName == 'contact') {
+ $contact = Toolkit_LeadManager_Contact::createByValues($values);
+ } else {
+ $contact = Toolkit_LeadManager_Customer::createByValues($values);
+ }
+
+ if ($contact->getMailOk()) {
+ if ( defined('STREAMSEND_FORMS_API')
+ && STREAMSEND_FORMS_API) {
+ $contact->attach(new Toolkit_LeadManager_StreamSend());
+ }
+ if ( defined('CONSTANT_CONTACT')
+ && CONSTANT_CONTACT) {
+ $contact->attach(new Toolkit_LeadManager_ConstantContact());
+ }
+ }
+
+ $contact->save($this->dbh, false);
+ return true;
+ }
+
+ // }}}
+ // {{{ setConfig()
+ /**
+ * setConfig
+ *
+ * @param Config_Container $c instance of Config Container
+ *
+ * @access public
+ * @return string
+ */
+ function setConfig(Config_Container $c)
+ {
+ $this->config = $c;
+ }// }}}
+ // {{{ 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);
+ }
+ }
+
+ // }}}
+ // {{{ setPrimaryKey()
+ /**
+ * setPrimaryKey
+ *
+ * @param mixed $fieldName Primary Key of Table
+ *
+ * @access public
+ * @return string
+ */
+ function setPrimaryKey($fieldName)
+ {
+ $this->primaryKey = $fieldName;
+ }// }}}
+ // {{{ setTableName()
+ /**
+ * setTableName
+ *
+ * @param mixed $tableName Database table name
+ *
+ * @access public
+ * @return string
+ */
+ function setTableName($tableName)
+ {
+ $this->tableName = $tableName;
+ }// }}}
+
+ // {{{ setupRenderers()
+ // @codeCoverageIgnoreStart
+
+ /**
+ * Custom rendering templates for special fields on the form
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ parent::setupRenderers();
+ $renderer =& $this->defaultRenderer();
+ $required = '<!-- BEGIN required -->
+ <span class="req"> * </span>
+ <!-- END required -->';
+ $error = '<!-- BEGIN error -->
+ <div class="req"> {error} </div>
+ <!-- END error -->';
+ $renderer->setElementTemplate(
+ '<tr>
+ <td colspan="2" class="fieldcell checkbox">
+ '.$required.'{label}'.$error.'{element}
+ </td>
+ </tr>',
+ 'interest'
+ );
+ if (is_array($this->interestsGroups)) {
+ foreach ($this->interestsGroups as $group => $gData) {
+ $renderer->setGroupTemplate(
+ '<br>{content}',
+ 'interest['.$group.']'
+ );
+ $renderer->setGroupElementTemplate(
+ '{element}',
+ 'interest['.$group.']'
+ );
+ $renderer->setElementTemplate(
+ '<tr>
+ <td colspan="2">'.$required.'{label}'.$error.'{element}
+ </td>
+ </tr>',
+ 'interest['.$group.']'
+ );
+ }
+ }
+ $renderer->setElementTemplate(
+ '<tr><td colspan="2">'.$required.'{label}'.$error.'{element}</td></tr>',
+ 'comments'
+ );
+ $renderer->setElementTemplate(
+ '<tr align="center">
+ <td colspan="2">'.$required.'{label}'.$error.'{element}
+ </td>
+ </tr>',
+ 'submit'
+ );
+
+ $renderer->setElementTemplate(
+ '<tr>
+ <td class="labelcell">
+ <label>{label}</label>
+ </td>
+ <td class="fieldcell captcha">
+ {element}
+ </td>
+ </tr>',
+ 'captcha_question');
+ $renderer->setElementTemplate(
+ '<tr>
+ <td class="labelcell">
+ '.$required.'<label>{label}</label>
+ </td>
+ <td class="fieldcell">
+ '.$error.'{element}
+ <span class="tooltip" title="Verification Code|To help us
+ distinguish between information submitted by individuals
+ and those automatically entered by software robots, please
+ type the letters shown.">What is this?</span>
+ </td>
+ </tr>',
+ '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->cleanForm();
+ if ($this->process(array(&$this, 'processData'), $this->mergeFiles)) {
+ $this->freeze();
+ $output = $this->successMsg;
+ header("Location: list_contact.phtml?back=1&start="
+ . $this->start . "&Action=" . $this->Action);
+ exit;
+ }
+ } elseif ($this->isSubmitted()) {
+ $output = $this->errorMsg;
+ $output .= parent::toHTML();
+ } else {
+ $output = parent::toHTML();
+ }
+ return $output;
+ }
+
+ // }}}
+
+}
--- /dev/null
+<?php
+// vim:set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker syntax=php:
+
+/**
+ * File Doc Comment
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Contacts
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: ContactUs.php,v 1.36 2010/07/14 23:33:15 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 Toolkit
+ * @package Contacts
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @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
+{
+
+ /**
+ * 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';
+ /**
+ * which groups to use on form if empty will grab all groups
+ */
+ protected $contactInqGroups = array();
+
+ /**
+ * 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.
+ * <code>
+ * protected $email = false;
+ * </code>
+ *
+ * @var string
+ * @access protected
+ */
+ protected $email;
+
+ /**
+ * From header in the owner email
+ *
+ * This just sets the From header in the owner email
+ * SITENAME <from@email.com>
+ *
+ * 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 <h1> 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 = '
+ <style type="text/css">
+ #category {display:none;}
+ .listing {display:none;}
+ </style>
+ <div id="form-success-top">
+ Thank you for your questions or comments!
+ </div>';
+
+ /**
+ * 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;
+
+ /**
+ * FormTemplate to use
+ *
+ * @var string
+ */
+ public $formTemplate = 'contactForm.html';
+
+ /**
+ * 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 <form> tag
+ * @param bool $trackSubmit (optional)Whether to track if the form was
+ * submitted by adding a special hidden field
+ *
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @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;
+
+ $conf = new Config;
+ $c =& $conf->parseConfig(
+ BASE . 'Toolkit/Contacts/config.ini',
+ 'IniFile'
+ );
+ $table = $c->getItem('section', 'conf')
+ ->getItem('directive', 'table')
+ ->getContent();
+ $this->tableName = $table;
+
+ // 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 = CONTACT_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 : MEDIA_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,
+ ),
+ );
+ $this->useCaptcha(true);
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * Initializes default form values
+ *
+ * @return void
+ * @access public
+ */
+ public function configureDefaults()
+ {
+ $defaults = array(
+ 'state' => '',
+ 'mail_ok' => 1
+ );
+ if (defined("MEMBERS_DB") && MEMBERS_DB) {
+ $defaults['members'] = 1;
+ }
+
+ $this->setupDefaults($defaults);
+ }
+
+ /**
+ * Form element definitions
+ *
+ * @return void
+ * @access public
+ */
+ public function configureElements()
+ {
+ $e = array();
+ if ($this->hasContactDB) {
+ $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' => 'header',
+ 'name' => 'firstHdr_rmv',
+ 'display' => ''
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'fname',
+ 'display' => 'First Name'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'lname',
+ 'display' => 'Last Name'
+ );
+ if ($this->tableName == 'customer') {
+ $add1 = 'add1';
+ $add2 = 'add2';
+ } else {
+ $add1 = 'address';
+ $add2 = 'address2';
+ }
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => $add1,
+ 'display' => 'Address 1'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => $add2,
+ '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' => 'email',
+ 'req' => true,
+ 'name' => 'email',
+ 'display' => 'Email'
+ );
+ $e[] = array(
+ 'type' => 'email',
+ 'req' => true,
+ 'name' => 'email_rmv',
+ 'display' => 'Verify Email'
+ );
+ $e[] = array(
+ 'type' => 'tel',
+ 'req' => false,
+ 'name' => 'phone',
+ 'display' => 'Phone'
+ );
+ $e[] = array(
+ 'type' => 'tel',
+ 'req' => false,
+ 'name' => 'fax',
+ 'display' => 'Fax'
+ );
+ $e[] = array(
+ 'type' => 'textarea',
+ 'req' => false,
+ 'name' => 'comments',
+ 'display' => 'Comments'
+ );
+ if ($this->hasContactDB) {
+ $e[] = array(
+ 'type' => 'advcheckbox',
+ 'req' => false,
+ 'name' => 'mail_ok',
+ 'display' => '',
+ 'opts' => 'Yes, I would like to receive Email Newsletters',
+ 'val' => array(0, 1)
+ );
+ if (defined("MEMBERS_DB") && MEMBERS_DB) {
+ $e[] = array(
+ 'type' => 'advcheckbox',
+ 'req' => false,
+ 'name' => 'members',
+ 'display' => '',
+ 'opts' => 'Yes, I would like to receive information via e-mail from '.SITENAME.' Members',
+ '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);
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * Helper function, configures the entire form
+ *
+ * @return void
+ * @access public
+ */
+ public function configureForm()
+ {
+ $this->configureElements();
+ $this->configureFilters();
+ $this->configureRules();
+ $this->configureDefaults();
+ $this->configureConstants();
+ }
+
+ /**
+ * 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);
+ }
+ }
+
+ /**
+ * Check for a contact or customer with given email address if found
+ * it returns the contact or customer id
+ *
+ * @param type $email Matching email for contact or customer
+ *
+ * @return integer
+ */
+ protected function getContactIdByEmail($email)
+ {
+ try {
+ $id = ($this->tableName == 'contact')
+ ? 'id'
+ : 'cust_id';
+ $sql = "
+ SELECT {$id}
+ FROM {$this->tableName}
+ WHERE email = :email";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':email', $email, PDO::PARAM_STR);
+ $stmt->execute();
+ return $stmt->fetchColumn();
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ /**
+ * 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;
+ }
+
+ $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'));
+
+ $userEmail = $this->getSubmitValue('email');
+ $page->email_from = GLM_TOOLBOX::valid_email(($userEmail))
+ ? $userEmail
+ : 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 ( isset($this->newInterest)
+ && is_array($this->newInterest)
+ && !empty($this->newInterest)
+ ) {
+ // Clean up the interests so they will look nice in the email
+ $page->formData['interest']['nowrap'] = 'nowrap';
+ $page->formData['interest']['element'] = null;
+
+ foreach ($this->newInterest as $group => $elements) {
+ $page->formData['interest['.$group.']']['label'] = $group;
+ foreach ($elements as $e => $vale) {
+ $interest[] = $this->inquiries[$group][$e];
+ }
+ $page->formData['interest['.$group.']']['element']
+ = implode("<br>", $interest);
+ unset($interest);
+ }
+ }
+
+ if ($this->elementExists('mail_ok')) {
+ // Clean up the mail_ok flag so its human readable
+ $page->formData['mail_ok']['label'] = 'Emails';
+ $page->formData['mail_ok']['element']
+ = ($page->formData['mail_ok']['element']) ? 'Yes' : 'No';
+ }
+
+ if (defined("MEMBERS_DB") && MEMBERS_DB) {
+ if ($this->elementExists('members')) {
+ // Clean up the mail_ok flag so its human readable
+ $page->formData['members']['label'] = 'Members';
+ $page->formData['members']['element']
+ = ($page->formData['members']['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");
+ $fromName = preg_replace(
+ '/[^A-Z ]/i', '',
+ $page->fname.' '.$page->lname
+ );
+ $mimeMail->setFrom("Website Form <".SERVER_FROM_EMAIL.">");
+ $mimeMail->setSubject($this->subject);
+ $mimeMail->setHTMLBody($htmlMsg);
+ $mimeMail->setTXTBody($msg);
+
+ $mail =& Mail::factory($mailFactory);
+ $body = $mimeMail->get();
+ $setHeader['Reply-To'] = sprintf(
+ '%1$s %2$s <%3$s>',
+ trim($this->getSubmitValue('fname'), "\r"),
+ trim($this->getSubmitValue('lname'), "\r"),
+ trim($this->getSubmitValue('email'), "\r")
+ );
+
+ $headers = $mimeMail->headers($setHeader);
+
+ $res = $mail->send($this->email, $headers, $body);
+ if (PEAR::isError($res)) {
+ return Toolkit_Common::handleError($res);
+ } else {
+ return $res;
+ }
+ }
+
+ /**
+ * 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 <i>' . $className . '</i> 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 <i>' . $className . '</i> before continuing',
+ MISSING_CONSTANT => 'You have failed to set a CONSTANT for the class <i>' . $className . '</i> to function properly',
+ MISSING_CONTACT_TYPE => 'Please set the property contactType in the class <i>'. $className . '</i> 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 "<div id=\"form-warning-top\">{$message}</div>";
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * 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)
+ {
+ unset($values['catid']);
+ // 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);
+
+ // 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']);
+ // setup newInterest aray with the interest values
+ // because their grouped can't be found with getElement('interest')
+ $this->newInterest = $values['interest'];
+ // update create_date for this contact
+ $values['create_date'] = date('m/d/Y');
+
+ // set up interest field values
+ 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) . ':';
+ }
+ }
+ if ($existingContact) {
+ $contactId = $this->getContactIdByEmail($values['email']);
+ $cType = $this->_getExistingContactTypes($contactId);
+ $idFieldName
+ = ($this->tableName == 'contact')
+ ? 'id'
+ : 'cust_id';
+ $values[$idFieldName] = $contactId;
+ $existingTypes
+ = (is_array($cType))
+ ? explode(':', $cType)
+ : array();
+ if (!in_array($this->contactType, $existingTypes)) {
+ $values['contact_type'] = "$cType{$this->contactType}:";
+ } else {
+ $values['contact_type'] = ":".implode(':', array_filter($existingTypes)).":";
+ }
+ } else {
+ $values['contact_type'] = ":{$this->contactType}:";
+ }
+ // build a contact or customer class object with the values from
+ // the Contact form
+ if ($this->tableName == 'contact') {
+ $contact = Toolkit_LeadManager_Contact::createByValues($values);
+ } else {
+ $contact = Toolkit_LeadManager_Customer::createByValues($values);
+ }
+ if ($contact->getMailOk()) {
+ if ( defined('STREAMSEND_FORMS_API')
+ && STREAMSEND_FORMS_API) {
+ $contact->attach(new Toolkit_LeadManager_StreamSend());
+ }
+ if ( defined('CONSTANT_CONTACT')
+ && CONSTANT_CONTACT) {
+ $contact->attach(new Toolkit_LeadManager_ConstantContact());
+ }
+ }
+ $contact->save($this->dbh, false);
+ return true;
+ }
+
+ /**
+ * Contact DB interests
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setInterestFields()
+ {
+ try {
+ $groupWhere
+ = (!empty($this->contactInqGroups))
+ ? "WHERE contact_inq.groupid IN (".implode(',',$this->contactInqGroups).")"
+ : "";
+ $sql = "
+ SELECT contact_inq.*, inq_group.name
+ FROM contact_inq
+ LEFT OUTER JOIN inq_group
+ ON (contact_inq.groupid = inq_group.id)
+ $groupWhere
+ ORDER BY inq_group.name, contact_inq.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);
+ }
+ }
+
+ // @codeCoverageIgnoreStart
+
+ /**
+ * Custom rendering templates for special fields on the form
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ $formConfig = new Zend_Config_Ini(
+ BASE . 'Toolkit/Contacts/application.ini',
+ strtolower($_ENV['GLM_HOST_ID'])
+ );
+
+ $renderer = new HTML_QuickForm_Renderer_Object(true);
+ $this->accept($renderer);
+ $this->template = new HTML_Template_Flexy(
+ $formConfig->flexyOptions->toArray()
+ );
+
+ $this->view = $this;
+ $this->view->form = $renderer->toObject();
+ $this->template->compile($this->formTemplate);
+ }
+
+ // @codeCoverageIgnoreEnd
+
+ /**
+ * 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()
+ {
+ if ($this->validate()) {
+ $this->captchaQuestion->destroy();
+ $this->cleanForm();
+ $this->setupRenderers();
+ 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('');
+ $this->setupRenderers();
+ $output = $this->errorMsg;
+ $output .= $this->template->bufferedOutputObject($this->view);
+ } else {
+ $this->captchaQuestion->destroy();
+ $this->captchaAnswer->setValue('');
+ $this->setupRenderers();
+ $output .= $this->template->bufferedOutputObject($this->view);
+ }
+ return $output;
+ }
+
+ /**
+ * Return the existing contact/customer contact_type
+ *
+ * @param type $contactId id of cust/contact
+ *
+ * @return type
+ */
+ protected function _getExistingContactTypes($contactId)
+ {
+ try {
+ $idField
+ = ($this->tableName == 'contact')
+ ? 'id'
+ : 'cust_id';
+ $sql = "
+ SELECT contact_type
+ FROM {$this->tableName}
+ WHERE {$idField} = :id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(':id', $contactId, PDO::PARAM_STR);
+ $stmt->execute();
+ return $stmt->fetchColumn();
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+}
+
--- /dev/null
+CREATE SCHEMA contacts;
+GRANT ALL ON SCHEMA contacts TO nobody;
+
+--
+-- Tables
+--
+\i ./tables/contact.sql
+\i ./tables/contact_inq.sql
+\i ./tables/inq_group.sql
+\i ./tables/query_db.sql
+\i ./tables/news_response.sql
+
+--
+-- Procedures
+--
--- /dev/null
+--
+-- This will drop everything in the contacts schema.
+-- Nothin better be in here except contact related object
+-- or it will be dropp
+--
+-- The force is strong w/ this one, use it wisely.
+--
+DROP SCHEMA IF EXISTS contacts CASCADE;
--- /dev/null
+DROP TABLE IF EXISTS contacts.contact CASCADE;
+
+CREATE TABLE contacts.contact
+(id SERIAL,
+ 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,
+ gift_cert BOOLEAN DEFAULT FALSE,
+ members BOOLEAN DEFAULT FALSE,
+ PRIMARY KEY (id));
+
+CREATE INDEX contact_create_date_indx ON contacts.contact USING btree(create_date);
+CREATE INDEX contact_email_indx ON contacts.contact USING btree(email);
+CREATE INDEX contact_fname_indx ON contacts.contact USING btree(fname);
+CREATE INDEX contact_lname_indx ON contacts.contact USING btree(lname);
+CREATE UNIQUE INDEX news_response_id_indx ON contacts.contact USING btree(id);
+CREATE UNIQUE INDEX query_db_id_indx ON contacts.contact USING btree(id);
+
+GRANT ALL ON contacts.contact_id_seq TO nobody;
+GRANT ALL ON contacts.contact TO nobody;
--- /dev/null
+DROP TABLE IF EXISTS contacts.contact_inq CASCADE;
+
+CREATE TABLE contacts.contact_inq
+(id SERIAL,
+ header text,
+ pos integer,
+ description text,
+ image text,
+ groupid integer,
+ PRIMARY KEY (id));
+
+GRANT ALL ON contacts.contact_inq_id_seq TO nobody;
+GRANT ALL ON contacts.contact_inq TO nobody;
--- /dev/null
+DROP TABLE IF EXISTS contacts.inq_group CASCADE;
+
+CREATE TABLE contacts.inq_group
+(id SERIAL,
+ name text,
+ PRIMARY KEY (id));
+
+GRANT ALL ON contacts.inq_group_id_seq TO nobody;
+GRANT ALL ON contacts.inq_group TO nobody;
+
+INSERT INTO contacts.inq_group (name) VALUES ('Interests');
\ No newline at end of file
--- /dev/null
+DROP TABLE IF EXISTS contacts.news_response;
+
+CREATE TABLE contacts.news_response
+(id SERIAL,
+ subject TEXT,
+ response TEXT,
+ image TEXT,
+ image2 TEXT,
+ image3 TEXT,
+ image_align TEXT,
+ image2_align TEXT,
+ image3_align TEXT,
+ mailout DATE DEFAULT CURRENT_DATE,
+ last_update DATE DEFAULT CURRENT_DATE,
+ PRIMARY KEY (id));
+
+GRANT ALL ON contacts.news_response_id_seq TO nobody;
+GRANT ALL ON contacts.news_response TO nobody;
+
+INSERT INTO contacts.news_response (subject, response) VALUES ('subject', 'response');
--- /dev/null
+DROP TABLE IF EXISTS contacts.query_db;
+
+CREATE TABLE contacts.query_db
+(id SERIAL,
+ query_name TEXT,
+ query TEXT,
+ file TEXT,
+ delimiter text,
+ PRIMARY KEY (id));
+
+GRANT ALL ON contacts.query_db_id_seq TO nobody;
+GRANT ALL ON contacts.query_db TO nobody;
--- /dev/null
+<?php
+// vim:set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker syntax=php:
+
+/**
+ * File Doc Comment
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Contacts
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: ContactUs.php,v 1.36 2010/07/14 23:33:15 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()
+ */
+
+/**
+ * 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 Toolkit
+ * @package Contacts
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit_FormBuilder
+ */
+class Toolkit_Contacts_ENewsSignup
+ extends Toolkit_Contacts_ContactUs
+{
+ /**
+ * 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 = '2';
+ /**
+ * Email subject and <h1> 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 = "ENews Signup Form from website";
+ /**
+ * Message to display if the form is successfully submitted
+ *
+ * @var string
+ * @access protected
+ */
+ protected $successMsg = '
+ <style type="text/css">
+ #category {display:none;}
+ .listing {display:none;}
+ </style>
+ <div id="form-success-top">
+ Thank you for requesting the ENewsetter.
+ </div>';
+ // {{{ configureConstats()
+
+ /**
+ * 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 <form> tag
+ * @param bool $trackSubmit (optional)Whether to track if the form was
+ * submitted by adding a special hidden field
+ *
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @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
+ ) {
+ parent::__construct(
+ $pdo,
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+ $this->email = ENEWS_EMAIL;
+ }
+
+ /**
+ * 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'],
+ 'mail_ok' => 1
+ );
+ $this->setupConstants($constants);
+ }
+
+ // }}}
+ // {{{ configureElements()
+
+ /**
+ * Form element definitions
+ *
+ * @return void
+ * @access public
+ */
+ public function configureElements()
+ {
+ $e = array();
+ if ($this->hasContactDB) {
+ $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' => 'header',
+ 'name' => 'firstHdr_rmv',
+ 'display' => ''
+ );
+ $e[] = array(
+ 'type' => 'email',
+ 'req' => true,
+ 'name' => 'email',
+ 'display' => 'Email'
+ );
+ $e[] = array(
+ 'type' => 'email',
+ 'req' => true,
+ 'name' => 'email_rmv',
+ 'display' => 'Verify Email'
+ );
+ if ($this->hasContactDB) {
+ $e[] = array(
+ 'type' => 'hidden',
+ 'req' => false,
+ 'name' => 'mail_ok',
+ );
+ }
+ $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);
+ }
+
+ // }}}
+}
--- /dev/null
+<?php
+// vim:set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker syntax=php:
+
+/**
+ * File Doc Comment
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Contacts
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link <>
+ */
+
+/**
+ * Ask the concierge form
+ *
+ * This form handles rendering and processing the contact form.
+ *
+ * @category Toolkit
+ * @package Contacts
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @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 = '3';
+
+ /**
+ * 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.
+ * <code>
+ * public $email = false;
+ * </code>
+ *
+ * @var unknown
+ * @access public
+ */
+ public $email = false;
+
+ /**
+ * Message to display if the form is successfully submitted
+ *
+ * @var string
+ * @access public
+ */
+ public $successMsg = '
+ <div id="form-success-top">
+ You have successfully created a new account.
+ </div>';
+
+ /**
+ * Email subject and <h1> 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 <form> 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' => 'header',
+ 'name' => 'infoHdr_rmv',
+ 'display' => ''
+ );
+ $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' => ', 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('<pre>'.print_r($row, true).'</pre>');
+ if (!empty($row)) {
+ return array(
+ 'contactId' => $row['id'],
+ 'password' => $row['password']
+ );
+ } else {
+ return false;
+ }
+
+ } 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);
+
+ // 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']);
+ // setup newInterest aray with the interest values
+ // because their grouped can't be found with getElement('interest')
+ $this->newInterest = $values['interest'];
+ // update create_date for this contact
+ $values['create_date'] = date('m/d/Y');
+
+ // set up interest field values
+ 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) . ':';
+ }
+ }
+
+ $values['password'] = md5($values['password']);
+ unset($values['catid']);
+ unset($values['cPage']);
+
+ $authContainer = new Toolkit_Members_TripPlanner_AuthContainer(
+ Toolkit_Database::getInstance(),
+ array(
+ 'table' => 'contact',
+ 'usernamecol' => 'email',
+ 'passwordcol' => 'password',
+ 'db_fields' => array('id', 'fname', 'lname'),
+ 'cryptType' => 'md5',
+ )
+ );
+
+ $tripPlannerAuth = new Toolkit_Members_TripPlanner_TripAuth(
+ $authContainer,
+ '',
+ 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']) {
+ $contactId = $existingContact['contactId'];
+ $cType = $this->_getExistingContactTypes($contactId);
+ $existingTypes
+ = (is_array($cType))
+ ? explode(':', $cType)
+ : array();
+ if (!in_array($this->contactType, $existingTypes)) {
+ $values['contact_type'] = "$cType{$this->contactType}:";
+ } else {
+ $values['contact_type'] = ":".implode(
+ ':', array_filter($existingTypes)
+ ).":";
+ }
+ // build a contact or customer class object with the values from
+ // the Contact form
+ if ($this->tableName == 'contact') {
+ $contact = Toolkit_LeadManager_Contact::createByValues($values);
+ } else {
+ $contact = Toolkit_LeadManager_Customer::createByValues($values);
+ }
+ if ( defined('STREAMSEND_FORMS_API')
+ && STREAMSEND_FORMS_API
+ && $values['mail_ok']) {
+ $contact->attach(new Toolkit_LeadManager_StreamSend());
+ }
+ $contact->save($this->dbh);
+ $tripPlannerAuth->setAuth($values['email']);
+ $tripPlannerAuth->setAuthData('id', $contactId);
+ $tripPlannerAuth->setAuthData('username', $values['email']);
+ $sessionList->saveList($contactId);
+ return true;
+ } else {
+ $seoUrl = Toolkit_Template_Page::getSeoUrl(
+ $this->_pageGateway, $this->plannerListPageId
+ );
+ $this->errorMsg = "<p>Your Email address already exist. Please "
+ . "<a href=\"$seoUrl\">sign-in</a>.</p>";
+ return false;
+ }
+ } else {
+ $values['contact_type'] = ":{$this->contactType}:";
+ // build a contact or customer class object with the values from
+ // the Contact form
+ if ($this->tableName == 'contact') {
+ $contact = Toolkit_LeadManager_Contact::createByValues($values);
+ } else {
+ $contact = Toolkit_LeadManager_Customer::createByValues($values);
+ }
+ if ( defined('STREAMSEND_FORMS_API')
+ && STREAMSEND_FORMS_API
+ && $values['mail_ok']) {
+ $contact->attach(new Toolkit_LeadManager_StreamSend());
+ }
+ $contact->save($this->dbh);
+ $contactId = $contact->getId();
+ // put in the creation of the contact record here
+ // and set contactId
+ $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;
+ }
+ }
+
+ // }}}
+
+ public function setGateway(Toolkit_Toolbox_PageGatewayAbstract $gateway)
+ {
+ $this->_pageGateway = $gateway;
+ }
+
+ // {{{ 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;
+ }
+
+ // }}}
+
+}
--- /dev/null
+<?php
+// vim:set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker syntax=php:
+
+/**
+ * File Doc Comment
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Contacts
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link <>
+ */
+
+/**
+ * Ask the concierge form
+ *
+ * This form handles rendering and processing the contact form.
+ *
+ * @category Toolkit
+ * @package Contacts
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @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 = '3';
+
+ /**
+ * 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.
+ * <code>
+ * public $email = false;
+ * </code>
+ *
+ * @var unknown
+ * @access public
+ */
+ public $email = false;
+
+ /**
+ * Message to display if the form is successfully submitted
+ *
+ * @var string
+ * @access public
+ */
+ public $successMsg = '
+ <style type="text/css">
+ #category {display:none;}
+ .listing {display:none;}
+ </style>
+ <div id="form-success-top">
+ <p>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.</p>
+ </div>';
+
+ /**
+ * Email subject and <h1> 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 <form> 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;
+ $successMsg = '
+ <style type="text/css">
+ #category {display:none;}
+ .listing {display:none;}
+ </style>
+ <div id="form-success-top">
+ <p>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 '.SITENAME.'.</p>
+ </div>';
+ }
+
+ // }}}
+ // {{{ 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' => 'header',
+ 'name' => 'infoHdr_rmv',
+ 'display' => ''
+ );
+ $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' => 'email',
+ 'req' => true,
+ 'name' => 'email',
+ 'display' => 'Email'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'email_rmv',
+ 'display' => 'Verify Email'
+ );
+ $e[] = array(
+ 'type' => 'tel',
+ 'req' => false,
+ 'name' => 'phone',
+ 'display' => 'Phone'
+ );
+ $e[] = array(
+ 'type' => 'tel',
+ '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' => '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);
+ }
+
+ // }}}
+
+ // {{{ 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('<br>', $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 <".SERVER_FROM_EMAIL.">");
+ $mimeMail->setSubject($this->subject);
+ $mimeMail->setHTMLBody($htmlMsg);
+ $mimeMail->setTXTBody($msg);
+
+ $mail =& Mail::factory('mail');
+ $body = $mimeMail->get();
+ $headerFormat = "%s %s <%s>";
+ $setHeader['Reply-To'] = sprintf(
+ $headerFormat,
+ $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);
+
+ if (defined('DEVELOPMENT') && DEVELOPMENT) {
+ // no emails sent
+ } else {
+ if (is_array($_SESSION['wish_list'])
+ && !empty($_SESSION['wish_list'])
+ ) {
+ foreach ($_SESSION['wish_list'] as $memberId => $row) {
+ try {
+ $getMemberEmail->bindParam(
+ ':member_id',
+ $memberId,
+ 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);
+ }
+ }
+ }
+ }
+ }
+ $authContainer = new Toolkit_Members_TripPlanner_AuthContainer(
+ Toolkit_Database::getInstance(),
+ array(
+ 'table' => 'contact',
+ 'usernamecol' => 'email',
+ 'passwordcol' => 'password',
+ 'db_fields' => array('id', 'fname', 'lname'),
+ 'cryptType' => 'md5',
+ )
+ );
+ $tripPlannerAuth = new Toolkit_Members_TripPlanner_TripAuth(
+ $authContainer,
+ '',
+ 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 $memberId => $row) {
+ try {
+ $getMemberData->bindParam(
+ ':member_id',
+ $memberId,
+ 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);
+ }
+ $name = preg_replace(
+ '/[\/#&?\'"]|amp;/',
+ '',
+ strip_tags(
+ strtolower(
+ trim(
+ str_replace(
+ ' ',
+ '-',
+ $memberData['member_name']
+ )
+ )
+ )
+ )
+ );
+ $memberUrl = MEDIA_BASE_URL
+ . "member-{$row['catid']}/" . htmlspecialchars($name)
+ . "-{$memberId}.html";
+ if ($memberData['member_contact_email']) {
+ $page->memberDirect[] = array(
+ 'memberName' => $memberName,
+ 'memberPhone' => $memberPhone,
+ 'memberTollFree' => $memberTollFree,
+ 'memberLink' => $memberUrl,
+ 'deleteLink' => MEDIA_BASE_URL
+ .'Toolkit/Members/TripPlanner/'
+ .'wish-list.php?catid='
+ .$_REQUEST['catid'].'&member_id=' . $memberId
+ . '&cPage=' . urlencode($_REQUEST['cPage']),
+ 'trclass' => (($mACount % 2 == 0) ? 'tr1': 'tr2')
+ );
+ $mACount++;
+ } else {
+ $page->memberDirectNoEmail[] = array(
+ 'memberName' => $memberName,
+ 'memberPhone' => $memberPhone,
+ 'memberTollFree' => $memberTollFree,
+ 'memberLink' => $memberUrl,
+ 'deleteLink' => MEDIA_BASE_URL
+ .'Toolkit/Members/TripPlanner/'
+ . 'wish-list.php?catid='
+ . $_REQUEST['catid'].'&member_id=' . $memberId
+ . '&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 = MEDIA_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;
+ }
+
+ // }}}
+}
+
--- /dev/null
+<?php
+/**
+ * StreamSend.php
+ *
+ * PHP version 5
+ *
+ * All Right Reserved
+ *
+ * @category Toolkit
+ * @package Contacts
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2009 Gaslight Media
+ * @license Gaslight Media
+ * @version CVS: $Id: StreamSend.php,v 1.5 2010/04/30 19:02:10 matrix 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 Toolkit
+ * @package Contacts
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @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',
+ 'interest' => 'interests',
+ 'contact_type' => 'contact-type'
+ );
+
+ /**
+ * 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;
+ $ret = $ss->contactSearch($values['email']);
+
+ $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';
+ }
+ }
+ if ($ret->contact) {
+ $contacts = $ss->contactUpdate(
+ $ret->contact->id,
+ $contactData
+ );
+ } else {
+ $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 "<p>A total and complete failure occured.";
+ break;
+ case "PRODUCTION":
+ break;
+ }
+ }
+ if ($ss->debug == true) {
+ echo '<p><h3>Debug Results</h3>'.$ss->debugBuffer.'</p>';
+ }
+ return true;
+ }
+ return false;
+ }
+
+
+ // }}}
+}
+?>
--- /dev/null
+<?php
+// vim:set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker syntax=php:
+
+/**
+ * File Doc Comment
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Contacts
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: ContactUs.php,v 1.36 2010/07/14 23:33:15 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()
+ */
+
+/**
+ * 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 Toolkit
+ * @package Contacts
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit_FormBuilder
+ */
+class Toolkit_Contacts_VisitorGuide
+ extends Toolkit_Contacts_ContactUs
+{
+ /**
+ * 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 = '4';
+ /**
+ * Message to display if the form is successfully submitted
+ *
+ * @var string
+ * @access protected
+ */
+ protected $successMsg = '
+ <style type="text/css">
+ #category {display:none;}
+ .listing {display:none;}
+ </style>
+ <div id="form-success-top">
+ Thank you for requesting the Visitors guide.
+ </div>';
+ /**
+ * Email subject and <h1> 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 = "Visitor Guide Form from website";
+
+ /**
+ * 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 <form> tag
+ * @param bool $trackSubmit (optional)Whether to track if the form was
+ * submitted by adding a special hidden field
+ *
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @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
+ ) {
+ parent::__construct(
+ $pdo,
+ $formName,
+ $method,
+ $action,
+ $target,
+ $attributes,
+ $trackSubmit
+ );
+ $this->email = VISITOR_GUIDE_EMAIL;
+ }
+ // {{{ configureConstants()
+
+ /**
+ * 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);
+ }
+
+ // }}}
+ // {{{ configureElements()
+
+ /**
+ * Form element definitions
+ *
+ * @return void
+ * @access public
+ */
+ public function configureElements()
+ {
+ $e = array();
+ if ($this->hasContactDB) {
+ $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' => 'header',
+ 'name' => 'firstHdr_rmv',
+ 'display' => ''
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'fname',
+ 'display' => 'First Name'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'lname',
+ 'display' => 'Last Name'
+ );
+ if ($this->tableName == 'customer') {
+ $add1 = 'add1';
+ $add2 = 'add2';
+ } else {
+ $add1 = 'address';
+ $add2 = 'address2';
+ }
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => $add1,
+ 'display' => 'Address 1'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => $add2,
+ 'display' => 'Address 2'
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'city',
+ 'display' => 'City'
+ );
+ $e[] = array(
+ 'type' => 'select',
+ 'req' => true,
+ 'name' => 'state',
+ 'display' => 'State/Province',
+ 'opts' => $GLOBALS['states']
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'zip',
+ 'display' => 'ZIP/Postal Code'
+ );
+ $e[] = array(
+ 'type' => 'email',
+ 'req' => true,
+ 'name' => 'email',
+ 'display' => 'Email'
+ );
+ $e[] = array(
+ 'type' => 'email',
+ 'req' => true,
+ 'name' => 'email_rmv',
+ 'display' => 'Verify Email'
+ );
+ $e[] = array(
+ 'type' => 'tel',
+ 'req' => false,
+ 'name' => 'phone',
+ 'display' => 'Phone'
+ );
+ $e[] = array(
+ 'type' => 'tel',
+ 'req' => false,
+ 'name' => 'fax',
+ 'display' => 'Fax'
+ );
+ $e[] = array(
+ 'type' => 'textarea',
+ 'req' => false,
+ 'name' => 'comments',
+ 'display' => 'Comments'
+ );
+ if ($this->hasContactDB) {
+ $e[] = array(
+ 'type' => 'advcheckbox',
+ 'req' => false,
+ 'name' => 'mail_ok',
+ 'display' => 'I would like to receive Email Newsletters',
+ 'opts' => 'Yes, ',
+ 'val' => array(0, 1)
+ );
+ if (defined("MEMBERS_DB") && MEMBERS_DB) {
+ $e[] = array(
+ 'type' => 'advcheckbox',
+ 'req' => false,
+ 'name' => 'members',
+ 'display' => 'I would like to receive information via e-mail from '.SITENAME.' Members',
+ '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);
+ }
+
+ // }}}
+}
--- /dev/null
+; Production server configuration data
+[production]
+previousYearSince = 2010
+
+; flexyOptions
+flexyOptions.templateDir = BASE "Toolkit/Contacts/templates"
+flexyOptions.compileDir = BASE "Toolkit/Contacts/templates/compiled"
+flexyOptions.forceCompile = Off
+flexyOptions.url_rewrite = "baseurl/::" BASE_URL ",glmappbaseurl/::" MEDIA_APP_BASE_URL
+flexyOptions.allowPHP = On
+
+; development server configuration data inherits from production and
+; overrides values as necessary
+[development : production]
+
+; chuck's server configuration data inherits from development
+; and overrides values as necessary
+[chuck : development]
+
+; steve's server configuration data inherits from development
+; and overrides values as necessary
+[steve : development]
--- /dev/null
+; Contact Database configuration file
+[conf]
+; Table Name for records
+table = "contact"
+; Primary Key
+primarykey = "id"
+; Sequence
+sequence = "contact_id_seq"
+
+[contact_types]
+1 = "Web Contact"
+2 = "E-News"
+3 = "Travel Planner"
+4 = "Visitor Guide"
--- /dev/null
+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);
--- /dev/null
+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
+);
--- /dev/null
+<link type="text/css" rel="stylesheet" href="<?php echo MEDIA_BASE_URL;?>css/contactform.css">
+<div flexy:if="pdfForm"><strong>DOWNLOAD:</strong>
+ <p>We will email you a link to the PDF version of the {brochure}.</p>
+</div>
+<div>
+ {pdfForm:h}
+</div>
+<p style="clear: both;" flexy:if="contactForm"><strong>ORDER BY MAIL:</strong></p>
+{contactForm:h}
--- /dev/null
+<div id="contact">
+ {form.javascript:h}
+ {form.outputHeader():h}
+ {form.hidden:h}
+ {hidden}
+ <table>
+ {foreach:form.sections,sec}
+ <tr>
+ <td class="header" colspan="2">
+ <b>{sec.header:h}</b></td>
+ </tr>
+ {foreach:sec.elements,elem}
+ {if:elem.style}
+ {elem.outputStyle():h}
+ {else:}
+ {if:elem.isButton()}
+ {if:elem.notFrozen()}
+ <tr>
+ <td class="labelcell"> </td>
+ <td class="fieldcell">{elem.html:h}</td>
+ </tr>
+ {end:}
+ {else:}
+ <tr>
+ {if:elem.isType(#textarea#)}
+ <td colspan="2">
+ {if:elem.required}<span class="req">*</span>{end:}
+ {if:elem.error}<div class="req">{end:}
+ {elem.label:h}<br>
+ {if:elem.error}</div>{end:}
+ {else:}
+ {if:elem.isType(#CAPTCHA_Image#)}
+ <td class="labelcell captcha">
+ {if:elem.required}<span class="req">*</span>{end:}
+ {if:elem.error}<div class="req">{end:}
+ {elem.label:h}
+ {if:elem.error}</div>{end:}
+ </td>
+ <td class="fieldcell">
+ {else:}
+ {if:elem.isType(#group#)}
+ <td colspan="2">
+ {if:elem.required}<span class="req">*</span>{end:}
+ {if:elem.error}<div class="req">{end:}
+ {elem.label:h}<br>
+ {if:elem.error}</div>{end:}
+ {else:}
+ <td class="labelcell">
+ {if:elem.required}<span class="req">*</span>{end:}
+ {if:elem.error}<div class="req">{end:}
+ {elem.label:h}
+ {if:elem.error}</div>{end:}
+ </td>
+ {if:elem.isName(#interest#)}
+ <td class="fieldcell checkbox">
+ {else:}
+ <td class="fieldcell">
+ {end:}
+ {end:}
+ {end:}
+ {end:}
+ {if:elem.error}<div class="error">{elem.error}</div>{end:}
+ {if:elem.isType(#group#)}
+ {foreach:elem.elements,gitem}
+ {gitem.label:h}
+ {gitem.html:h}{if:gitem.required}<div class="req">*</div>{end:}
+ {if:elem.separator}{elem.separator:h}{end:}
+ {end:}
+ {else:}
+ {elem.html:h}
+ {if:elem.isName(#captcha_rmv#)}
+ <span
+ class="tooltip"
+ title="Verification Code|To help us distinguish between
+ information submitted by individuals and those automatically
+ entered by software robots, please type the letters shown.">What is this?
+ </span>
+ {end:}
+ {end:}
+ </td>
+ </tr>
+ {end:}
+ {end:}
+ {end:} <!-- end for foreach:sec.element,elem -->
+ {end:} <!-- end for foreach:form.section,sec -->
+
+ </table>
+ </form>
+ {if:form.requirednote}
+ <div>{form.requirednote:h}</div>
+ {end:}
+</div>
--- /dev/null
+<tr>
+ <td class="labelcell">
+ <!-- BEGIN required -->
+ <span class="req">*</span>
+ <!-- END required -->
+ <label>{label}</label>
+ </td>
+ <td class="fieldcell">
+ <!-- BEGIN error -->
+ <div class="req"> {error} </div>
+ <!-- END error -->
+ {element}
+ </td>
+</tr>
--- /dev/null
+<div id="contact">
+ <form{attributes}>
+ {hidden}
+ <table>
+ {content}
+ </table>
+ </form>
+</div>
\ No newline at end of file
--- /dev/null
+<table class="group">
+ <tbody>
+ {content}
+ </tbody>
+</table>
--- /dev/null
+<tr>
+ <td>
+ {element}
+ <!-- BEGIN required -->
+ <span class="req">*</span>
+ <!-- END required -->
+ {label}
+ </td>
+</tr>
--- /dev/null
+<tr class="hdr">
+ <td colspan="2">
+ {header}
+ </td>
+</tr>
--- /dev/null
+<span class="req">* = Required Fields</span>
--- /dev/null
+<h1>Your Trip Planner List</h1>
+<p>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.</p>
+<h2 flexy:if="memberDirectNoEmail">Request Information by Phone from:</h2>
+<p>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.</p>
+<table flexy:if="memberDirectNoEmail">
+ <tr>
+ <th>Name</td>
+ <th>Phone</td>
+ <th> </td>
+ </tr>
+ {foreach:memberDirectNoEmail,member}
+ <tr class="{member[trclass]}">
+ <td><a href="{member[memberLink]}">{member[memberName]}</a></td>
+ <td>{member[memberPhone]}</td>
+ <td class="rowDelete"><a href="{member[deleteLink]}" style="text-decoration: underline;">Remove</a></td>
+ </tr>
+ {end:}
+</table>
+<h2 flexy:if="memberDirect">Request Information by Email from:</h2>
+<p flexy:if="memberDirect">This list of businesses will receive the following information form directly to their email account.</p>
+<table flexy:if="memberDirect">
+ {foreach:memberDirect,member}
+ <tr class="{member[trclass]}">
+ <td><a href="{member[memberLink]}">{member[memberName]}</a></td>
+ <td class="rowDelete"><a href="{member[deleteLink]}" style="text-decoration: underline;">Remove</a></td>
+ </tr>
+ {end:}
+</table>
+<h2 flexy:if="memberDirect">Plan Your Trip Information Request Form</h2>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
+ <title>{title:h}</title>
+</head>
+<body>
+ <!-- {{{ body -->
+ <p>
+ <font size="4" face="arial, sans-serif">
+ <b>{subject:h}</b>
+ </font>
+ </p>
+ <p>
+ <font size="3" face="arial, sans-serif">
+ <b>From {fname:h} {lname:h}</b>
+ </font>
+ </p>
+ <table cellspacing="0" cellpadding="0" bgcolor="#c0c0c0" border="0">
+ <tr>
+ <td>
+ <table cellspacing="1" cellpadding="5" border="0" bgcolor="#c0c0c0" width="400">
+ {foreach:formData,v}
+ <tr flexy:if="v[element]" bgcolor="#c0c0c0">
+ <td align="right" bgcolor="#ffffff">
+ <font size="2" face="arial, sans-serif">
+ <b>{v[label]:h}</b>
+ </font>
+ </td>
+ {if:v[nowrap]}
+ <td nowrap bgcolor="#ffffff">
+ <font size="2" face="arial, sans-serif">{v[element]:h}</font>
+ </td>
+ {else:}
+ <td bgcolor="#ffffff">
+ <font size="2" face="arial, sans-serif">{v[element]:h}</font>
+ </td>
+ {end:}
+ </tr>
+ {end:}
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <table cellspacing="0" cellpadding="10" border="0" width="400">
+ <tr>
+ <td bgcolor="#eeeeee">
+ <font size="1" face="arial, sans-serif">
+ 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.
+ </font>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ </table>
+ <!-- }}} -->
+</body>
+</html>
--- /dev/null
+<html>
+ <style type="text/css">
+ <!--
+ body { background-color: #fff;
+ color: black;
+ font-family: verdana, arial, helvetica, sans-serif;
+ }
+ h1, h2 {font-family: arial, helvetica, sans-serif;}
+ h1 {font-size: 18px; }
+ h2 {font-size: 16px; margin-bottom: 5px;}
+ p {font-size: 12px;}
+ .label {
+ font-weight: bold;
+ background-color: transparent;
+ text-align: right;
+ width: 200px;
+ padding: 5px;
+ }
+ .field {
+ //background-color: #F2F7FB;
+ background-color: #fff;
+ padding: 3px;
+ }
+ table.data {
+ //background-color: #F9FBFD;
+ background-color: #fff;
+ color: #000;
+ width: 500px;
+ //border: 1px solid #D7E5F2;
+ border: 1px solid #ccc;
+ border-collapse: collapse;
+ margin-left: 20px;
+ }
+ table.data td {
+ //border: 1px solid #D7E5F2;
+ border: 1px solid #ccc;
+ padding-left: 4px;
+ font-size: 12px;
+ }
+ -->
+</style>
+<body>
+
+ <p>Dear {fname}</p>
+ <p>Your friend {yname} has been to <a href="baseurl">demo.gaslightmedia.com</a>, and thought you might be interested in it. </p>
+ <p>Message here.</p>
+ <div> </div><br clear="all">
+</body>
+</html>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
+ <title>{title:h}</title>
+</head>
+<body>
+ <!-- {{{ body -->
+ <b>{subject:h}</b>
+ <p>Thank you for requesting the {pdfName} Link. Here is the link to the Adobe PDF version:
+ </p>
+ <p><a href="{pdfLinkURL}">Brochure</a> ({pdfFileSize})</p>
+ <p>Thank you for your interest in {client_info[name]:h}'!</p>
+ <p>Sincerely,</p>
+ <p>{client_info[name]:h}</p>
+ <p>{client_info[url]:h}</p>
+ <!-- }}} -->
+</body>
+</html>
--- /dev/null
+<?php
+// vim:set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker syntax=php:
+
+/**
+ * File Doc Comment
+ *
+ * PHP version 5
+ *
+ * @category Coupons
+ * @package Toolkit_Coupons
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: AdminEditCategoryForm.php,v 1.1 2010/02/12 21:16:32 jamie Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Coupon Category form
+ *
+ * Manages the creation and editing form for manipulating coupon categories
+ *
+ * @category Coupons
+ * @package Toolkit_Coupons
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Coupons_AdminEditCategoryForm extends Toolkit_FormBuilder
+{
+ // {{{ properties
+
+ /**
+ * Success msg if the form validates successfully
+ *
+ * @var string
+ * @access protected
+ */
+ protected $successMsg
+ = '<div id="form-success-top">Category successfully updated.</div>';
+
+ /**
+ * 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.
+ *
+ * @var string
+ * @access protected
+ */
+ protected $registeredRules = array();
+
+ // }}}
+
+ // {{{ configureDefaults()
+
+ /**
+ * Configure the initial default values for the form
+ *
+ * @param PDO $dbh Database handler
+ *
+ * @return void
+ * @access protected
+ */
+ public function configureDefaults(PDO $dbh)
+ {
+ if (ctype_digit($_GET['id'])) {
+ try {
+ $sql = "
+ SELECT name
+ FROM coupon_category
+ WHERE id= :id";
+
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(':id', $_GET['id'], PDO::PARAM_STR);
+ $stmt->execute();
+
+ $d = $stmt->fetch(PDO::FETCH_ASSOC);
+ } catch (PDOException $e) {
+ Toolkit_Logger::logException('DB Error', $e);
+ throw new Toolkit_Coupons_Exception(
+ 'Error configuring category default value'
+ );
+ }
+ } else {
+ $d = array();
+ }
+
+ $this->setupDefaults($d);
+ }
+
+ // }}}
+ // {{{ configureElements()
+
+ /**
+ * Configure how the form elements should look
+ *
+ * @return void
+ * @access public
+ */
+ public function configureElements()
+ {
+ $e = array();
+
+ // All Grouped Elements are created here.
+
+ // All Elements are created here. This includes group element definitions.
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'name',
+ 'display' => 'Category',
+ 'opts' => array('class' => 'text')
+ );
+ $e[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'submit',
+ 'display' => 'Submit Category',
+ 'opts' => array('id' => 'submit')
+ );
+ if (ctype_digit($_GET['id'])) {
+ $e[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'delete',
+ 'display' => 'Delete Category',
+ 'opts' => array('id' => 'delete')
+ );
+ }
+
+ $this->setupElements($e);
+ }
+
+ // }}}
+ // {{{ configureFilters()
+
+ /**
+ * Configure how the form elements should act when being submitted
+ *
+ * @return void
+ * @access protected
+ */
+ public function configureFilters()
+ {
+ $f = array();
+ $f[] = array(
+ 'element' => '__ALL__',
+ 'filter' => 'trim'
+ );
+
+ $this->setupFilters($f);
+ }
+
+ // }}}
+ // {{{ configureForm()
+
+ /**
+ * Configure a form so we can use it
+ *
+ * @param PDO $dbh Database handler
+ *
+ * @return void
+ * @access public
+ */
+ public function configureForm(PDO $dbh)
+ {
+ $this->configureElements();
+ $this->configureFilters();
+ $this->configureRules();
+ $this->configureDefaults($dbh);
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Configure how the form elements should act
+ *
+ * @return void
+ * @access public
+ */
+ public function configureRules()
+ {
+ $r = array();
+
+ $this->setupRules($r);
+ }
+
+ // }}}
+
+ // {{{ _processData()
+
+ /**
+ * Determine how the form should be handled (insert new data or update old)
+ *
+ * @param PDO $dbh Database handler
+ * @param array $values Submitted form values
+ *
+ * @return boolean Result of insert or update function
+ * @access private
+ */
+ private function _processData(PDO $dbh, array $values)
+ {
+ if (isset($values['delete']) && ctype_digit($_GET['id'])) {
+ $category = Toolkit_Coupons_Category::fetch($dbh, $_GET['id']);
+ return $category->delete($dbh);
+ } elseif (ctype_digit($_GET['id'])) {
+ $category = Toolkit_Coupons_Category::fetch($dbh, $_GET['id']);
+ $category->setName($values['name']);
+ return $category->update($dbh);
+ } else {
+ $category = new Toolkit_Coupons_Category($values['name']);
+ return $category->save($dbh);
+ }
+ }
+
+ // }}}
+
+ // {{{ setupRenderers()
+ // @codeCoverageIgnoreStart
+
+ /**
+ * Custom rendering templates for special fields on the form
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ parent::setupRenderers();
+ $renderer = $this->defaultRenderer();
+ $required
+ = "<!-- BEGIN required -->\n
+ <span class=\"req\"> * </span>\n
+ <!-- END required -->";
+ $error
+ = "<!-- BEGIN error -->\n
+ <div class=\"req\"> {error} </div>\n
+ <!-- END error -->";
+ $renderer->setElementTemplate(
+ "<tr align=\"center\">\n
+ <td colspan=\"2\">$required{label}$error{element}</td>\n
+ </tr>",
+ 'submit'
+ );
+ $renderer->setElementTemplate(
+ "<tr align=\"center\">\n
+ <td colspan=\"2\">$required{label}$error{element}</td>\n
+ </tr>",
+ 'delete'
+ );
+
+ }
+
+ // @codeCoverageIgnoreEnd
+ // }}}
+
+ // {{{ toHtml()
+
+ /**
+ * Call the rendering function to get the form in a string
+ *
+ * @param PDO $dbh Database handler
+ *
+ * @return string $output The Form to be rendered or success msg.
+ * @access protected
+ */
+ public function toHtml(PDO $dbh)
+ {
+ $GLOBALS['styleSheets'][] = MEDIA_BASE_URL . 'css/contactform.css';
+
+ $this->setupRenderers();
+ if ($this->validate()) {
+ $this->cleanForm();
+
+ if ($this->_processData($dbh, $this->getSubmitValues())) {
+ $this->freeze();
+ $output = $this->successMsg;
+ }
+ } elseif ($this->isSubmitted()) {
+ $output = $this->errorMsg;
+ $output .= parent::toHTML();
+ } else {
+ $output = parent::toHTML();
+ }
+ return $output;
+ }
+
+ // }}}
+}
+?>
--- /dev/null
+<?php
+// vim:set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker syntax=php:
+
+/**
+ * File Doc Comment
+ *
+ * PHP version 5
+ *
+ * @category Banners
+ * @package Toolkit_Banners
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: AdminEditCouponForm.php,v 1.2 2010/07/06 12:49:55 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+require_once BASE . 'Toolkit/Forms/Rules/Date.php';
+
+/**
+ * Banner Ad Application
+ *
+ * Manages the creation and editing form for manipulating banners in the db.
+ *
+ * @category Banners
+ * @package Toolkit_Banners
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Coupons_AdminEditCouponForm extends Toolkit_FormBuilder
+{
+ // {{{ properties
+
+ /**
+ * What do you want the success msg to be if the form validates successfully
+ *
+ * @var string
+ * @access protected
+ */
+ protected $successMsg
+ = '<div id="form-success-top">Coupon successfully updated.</div>';
+
+ /**
+ * 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.
+ *
+ * @var string
+ * @access protected
+ */
+ protected $registeredRules = array(
+ array(
+ 'checkURI',
+ 'callback',
+ 'uri',
+ 'Validate'
+ )
+ );
+
+ // }}}
+
+ // {{{ checkDates()
+
+ /**
+ * Check that start date does not come before end date
+ *
+ * @param array $dates Multi-Dimensional array of dates.
+ *
+ * @return boolean false if start is after end, else true
+ * @access public
+ */
+ public function checkDates(array $dates)
+ {
+ extract($dates[0], EXTR_PREFIX_ALL, 'start');
+ extract($dates[1], EXTR_PREFIX_ALL, 'end');
+
+ $start = strtotime("$start_m/$start_d/$start_Y");
+ $end = strtotime("$end_m/$end_d/$end_Y");
+
+ $sdate = new Date();
+ $sdate->setDate($start, DATE_FORMAT_UNIXTIME);
+ $edate = new Date();
+ $edate->setDate($end, DATE_FORMAT_UNIXTIME);
+
+ return (Date::compare($sdate, $edate) < 1);
+ }
+
+ // }}}
+ // {{{ configureConstants()
+
+ /**
+ * Configure form constants
+ *
+ * @return void
+ * @access public
+ */
+ public function configureConstants()
+ {
+ $c = array();
+
+ // If we are adding a new coupon
+ if (!ctype_digit($_GET['id'])) {
+ $c['current_image_rmv'] = 'Image not yet uploaded';
+ }
+
+ // If the form has been submitted and a new image was uploaded
+ $currImg = $this->getSubmitValue('image');
+ if ($this->isSubmitted() && !empty($currImg)) {
+ $img = '<img src="%s%s">';
+ $c['current_image_rmv'] = sprintf($img, COUPON_THUMB, $currImg);
+ }
+
+ $this->setupConstants($c);
+ }
+
+ // }}}
+ // {{{ configureDefaults()
+
+ /**
+ * Configure the initial default values for the form
+ *
+ * @param PDO $dbh Database handler
+ * @param Toolkit_Coupons_ThumbnailFactory $cFactory Thumbnail Factory
+ * @param Toolkit_Coupons_CouponFactory $cFactory Coupon Factory
+ *
+ * @return void
+ * @access protected
+ */
+ public function configureDefaults(
+ PDO $dbh,
+ Toolkit_Coupons_ThumbnailFactory $tFactory,
+ Toolkit_Coupons_CouponFactory $cFactory
+ ) {
+ if (ctype_digit($_GET['id'])) {
+ $coupon = $cFactory->fetch($dbh, $_GET['id']);
+ if (!is_null($coupon->getImage()->getSrc())) {
+ $thumbnailDecorator = $tFactory->createDecorator($coupon);
+ $thumbnail = $thumbnailDecorator->toHtml();
+ $thumbnail .= '<br><label>'
+ . '<input type="hidden" name="old_image_rmv" value="'
+ . $coupon->getImage()->getSrc()
+ . '">'
+ . '<input type="checkbox" name="del_image_rmv" value="1">'
+ . 'Delete Image?'
+ . '</label>';
+ } else {
+ $thumbnail = 'Image not yet uploaded';
+ }
+ $d = array(
+ 'active' => $coupon->getActive(),
+ 'category' => $coupon->getCategory(),
+ 'title' => $coupon->getTitle(),
+ 'description' => $coupon->getDescription(),
+ 'url' => $coupon->getUrl(),
+ 'image' => $coupon->getImage()->getSrc(),
+ 'current_image_rmv' => $thumbnail,
+ 'sdate' => array(
+ 'm' => $coupon->getSdate()->getMonth(),
+ 'd' => $coupon->getSdate()->getDay(),
+ 'Y' => $coupon->getSdate()->getYear()
+ ),
+ 'edate' => array(
+ 'm' => $coupon->getEdate()->getMonth(),
+ 'd' => $coupon->getEdate()->getDay(),
+ 'Y' => $coupon->getEdate()->getYear()
+ ),
+ 'expiration' => array(
+ 'm' => $coupon->getExpiration()->getMonth(),
+ 'd' => $coupon->getExpiration()->getDay(),
+ 'Y' => $coupon->getExpiration()->getYear()
+ ),
+ );
+ if (defined('MEMBERS_DB') && MEMBERS_DB) {
+ $d['member'] = $coupon->getMember();
+ $d['pending'] = $coupon->getPending();
+ }
+ } else {
+ $date = new Date();
+ $sdateMonth = $date->getMonth();
+ $sdateDay = $date->getDay();
+ $sdateYear = $date->getYear();
+
+ $date->addMonths(6);
+
+ $edateMonth = $date->getMonth();
+ $edateDay = $date->getDay();
+ $edateYear = $date->getYear();
+ $d = array(
+ 'sdate' => array(
+ 'm' => $sdateMonth,
+ 'd' => $sdateDay,
+ 'Y' => $sdateYear
+ ),
+ 'edate' => array(
+ 'm' => $edateMonth,
+ 'd' => $edateDay,
+ 'Y' => $edateYear
+ ),
+ 'expiration' => array(
+ 'm' => $edateMonth,
+ 'd' => $edateDay,
+ 'Y' => $edateYear
+ ),
+ );
+ if (defined('MEMBERS_DB') && MEMBERS_DB) {
+ $d['member'] = null;
+ $d['pending'] = 0;
+ }
+ }
+
+ $this->setupDefaults($d);
+ }
+
+ // }}}
+ // {{{ configureElements()
+
+ /**
+ * Configure how the form elements should look
+ *
+ * @param PDO $dbh Database handler
+ * @param Config_Container $c Configuration object
+ *
+ * @return void
+ * @access public
+ */
+ public function configureElements(PDO $dbh, Config_Container $c)
+ {
+ $e = array();
+
+ $categories = $this->_getCategories($dbh);
+ if (defined('MEMBERS_DB') && MEMBERS_DB) {
+ $members = $this->_getMembers($dbh);
+ $conf = new Config;
+ $memberDbListingType = $conf->parseConfig(
+ BASE . 'Toolkit/Members/config.ini',
+ 'IniFile'
+ )->getItem('section', 'listing type')
+ ->getItem('directive', 'singular')
+ ->getContent();
+ }
+
+ $minYear = $c->getItem('section', 'conf')
+ ->getItem('directive', 'minYear')
+ ->getContent();
+
+ // All Grouped Elements are created here.
+
+ // All Elements are created here. This includes group element definitions.
+ $e[] = array(
+ 'type' => 'advcheckbox',
+ 'req' => false,
+ 'name' => 'active',
+ 'display' => 'Active',
+ 'val' => array(0, 1)
+ );
+ if (defined('MEMBERS_DB') && MEMBERS_DB) {
+ $e[] = array(
+ 'type' => 'select',
+ 'req' => false,
+ 'name' => 'member',
+ 'display' => $memberDbListingType,
+ 'opts' => array('' => '-- Select --') + $members
+ );
+ $e[] = array(
+ 'type' => 'hidden',
+ 'req' => false,
+ 'name' => 'pending',
+ );
+ }
+ $e[] = array(
+ 'type' => 'select',
+ 'req' => true,
+ 'name' => 'category',
+ 'display' => 'Category',
+ 'opts' => array('' => '-- Select --') + $categories
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'title',
+ 'display' => 'Title',
+ 'opts' => array('class' => 'text')
+ );
+ $e[] = array(
+ 'type' => 'textarea',
+ 'req' => false,
+ 'name' => 'description',
+ 'display' => 'Description <span id="charleft">600</span> characters left',
+ 'opts' => array('id' => 'description')
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'url',
+ 'display' => 'Website Link',
+ );
+ $e[] = array(
+ 'type' => 'static',
+ 'req' => false,
+ 'name' => 'current_image_rmv',
+ 'display' => 'Current Coupon Image'
+ );
+ $e[] = array(
+ 'type' => 'hidden',
+ 'req' => false,
+ 'name' => 'image'
+ );
+ $e[] = array(
+ 'type' => 'file',
+ 'req' => false,
+ 'name' => 'file_rmv',
+ 'display' => 'New Coupon Image'
+ );
+ $e[] = array(
+ 'type' => 'static',
+ 'req' => false,
+ 'name' => 'img_instructions_rmv',
+ 'opts' => '.jpg or .gif images only'
+ );
+ $e[] = array(
+ 'type' => 'date',
+ 'req' => true,
+ 'name' => 'sdate',
+ 'display' => 'Start Date',
+ 'opts' => array(
+ 'format' => 'm / d / Y',
+ 'minYear' => $minYear,
+ 'maxYear' => date('Y') + 5,
+ 'addEmptyOption' => true,
+ 'emptyOptionText' => array(
+ 'm' => 'mm',
+ 'd' => 'dd',
+ 'Y' => 'yyyy'
+ )
+ ),
+ 'att' => array('id' => 'sdate')
+ );
+ $e[] = array(
+ 'type' => 'date',
+ 'req' => true,
+ 'name' => 'edate',
+ 'display' => 'End Date',
+ 'opts' => array(
+ 'format' => 'm / d / Y',
+ 'minYear' => $minYear,
+ 'maxYear' => date('Y') + 5,
+ 'addEmptyOption' => true,
+ 'emptyOptionText' => array(
+ 'm' => 'mm',
+ 'd' => 'dd',
+ 'Y' => 'yyyy'
+ )
+ ),
+ 'att' => array('id' => 'edate')
+ );
+ $e[] = array(
+ 'type' => 'date',
+ 'req' => true,
+ 'name' => 'expiration',
+ 'display' => 'Expire Date',
+ 'opts' => array(
+ 'format' => 'm / d / Y',
+ 'minYear' => $minYear,
+ 'maxYear' => date('Y') + 5,
+ 'addEmptyOption' => true,
+ 'emptyOptionText' => array(
+ 'm' => 'mm',
+ 'd' => 'dd',
+ 'Y' => 'yyyy'
+ )
+ ),
+ 'att' => array('id' => 'expiration')
+ );
+ $e[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'submit_rmv',
+ 'display' => 'Submit Coupon',
+ 'opts' => array('id' => 'submit')
+ );
+ if (ctype_digit($_GET['id'])) {
+ $e[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'delete_rmv',
+ 'display' => 'Delete Coupon',
+ 'opts' => array(
+ 'id' => 'delete',
+ 'onClick' => 'return confirm(\'This will delete the Coupon\nAre You Sure?\');'
+ )
+ );
+ }
+
+ $this->setupElements($e);
+ }
+
+ // }}}
+ // {{{ configureFilters()
+
+ /**
+ * Configure how the form elements should act when being submitted
+ *
+ * @return void
+ * @access protected
+ */
+ public function configureFilters()
+ {
+ $f = array();
+ $f[] = array(
+ 'element' => '__ALL__',
+ 'filter' => 'trim'
+ );
+ $f[] = array(
+ 'element' => 'url',
+ 'filter' => array('Toolkit_Common', 'filterURI')
+ );
+
+ $this->setupFilters($f);
+ }
+
+ // }}}
+ // {{{ configureForm()
+
+ /**
+ * Configure a form so we can use it
+ *
+ * @param PDO $dbh Database handler
+ * @param Config_Container $c Application configuration settings
+ * @param Toolkit_Coupons_ThumbnailFactory $cFactory Thumbnail Factory
+ * @param Toolkit_Coupons_CouponFactory $cFactory Coupon Factory
+ *
+ * @return void
+ * @access public
+ */
+ public function configureForm(
+ PDO $dbh,
+ Config_Container $c,
+ Toolkit_Coupons_ThumbnailFactory $tFactory,
+ Toolkit_Coupons_CouponFactory $cFactory
+ ) {
+ $this->configureElements($dbh, $c);
+ $this->configureFilters();
+ $this->configureRules();
+ $this->configureDefaults($dbh, $tFactory, $cFactory);
+ $this->configureConstants();
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Configure how the form elements should act
+ *
+ * @return void
+ * @access public
+ */
+ public function configureRules()
+ {
+ $r = array();
+
+ $mimeTypes = array(
+ 'image/jpe',
+ 'image/jpeg',
+ 'image/jpg',
+ 'image/jfif',
+ 'image/pjpeg',
+ 'image/pjp',
+ 'image/gif',
+ 'image/png',
+ );
+
+ $r[] = array(
+ 'element' => 'url',
+ 'message' => 'ERROR: Invalid URL format (http, https only)',
+ 'type' => 'checkURI',
+ 'format' => array(
+ 'allowed_schemes' => array('http', 'https'),
+ 'strict' => true
+ ),
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => 'sdate',
+ 'message' => 'ERROR: Invalid Date!',
+ 'type' => 'Date',
+ 'format' => array('format' => '%m-%d-%Y'),
+ 'validation' => $this->validationType,
+ 'reset' => true,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => 'edate',
+ 'message' => 'ERROR: Invalid Date!',
+ 'type' => 'Date',
+ 'format' => array('format' => '%m-%d-%Y', 'allowEmpty' => true),
+ 'validation' => $this->validationType,
+ 'reset' => true,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => 'expiration',
+ 'message' => 'ERROR: Invalid Date!',
+ 'type' => 'Date',
+ 'format' => array('format' => '%m-%d-%Y', 'allowEmpty' => true),
+ 'validation' => $this->validationType,
+ 'reset' => true,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => array('sdate', 'edate'),
+ 'message' => 'ERROR: Start Date must be less than or equal to End Date!',
+ 'type' => 'callback',
+ 'format' => array(&$this, 'checkDates'),
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ $r[] = array(
+ 'element' => array('edate', 'expiration'),
+ 'message' => 'ERROR: End Date must be less than or equal to Expire Date!',
+ 'type' => 'callback',
+ 'format' => array(&$this, 'checkDates'),
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ if (is_uploaded_file($_FILES['file_rmv']['tmp_name'])) {
+ $r[] = array(
+ 'element' => 'file_rmv',
+ 'message' => 'ERROR: Incorrect File Type (.gif, .png, .jpg) only!',
+ 'type' => 'mimetype',
+ 'format' => $mimeTypes,
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+ }
+
+ $this->setupRules($r);
+ }
+
+ // }}}
+
+ // {{{ _getCategories()
+
+ /**
+ * Get the array of coupon categories used for the select list
+ *
+ * @param PDO $dbh Database handler
+ *
+ * @return array categories used to populate a select list element
+ * @access protected
+ */
+ private function _getCategories(PDO $dbh)
+ {
+ // Get only the active categories from
+ // the nav structure for our select list.
+ $sql = "
+ SELECT *
+ FROM coupon_category
+ ORDER BY name";
+
+ $categories = array();
+ foreach ($dbh->query($sql, PDO::FETCH_ASSOC) as $row) {
+ $categories[$row['name']] = $row['name'];
+ }
+ return $categories;
+ }
+
+ // }}}
+ // {{{ _getMembers()
+
+ /**
+ * Get the array of members used for the select list
+ *
+ * @param PDO $dbh Database handler
+ *
+ * @return array members used to populate a select list element
+ * @access protected
+ */
+ private function _getMembers(PDO $dbh)
+ {
+ // Get only the active members from
+ $sql = "
+ SELECT *
+ FROM member
+ ORDER BY member_name";
+
+ $members = array();
+ foreach ($dbh->query($sql, PDO::FETCH_ASSOC) as $row) {
+ $members[$row['member_id']] = $row['member_name'];
+ }
+
+ return $members;
+ }
+
+ // }}}
+
+ // {{{ _processData()
+
+ /**
+ * Determine how the form should be handled (insert new data or update old)
+ *
+ * @param PDO $dbh Database handler
+ * @param array $values Submitted form values
+ * @param Toolkit_Coupons_CouponFactory $cFactory Coupon Factory
+ *
+ * @return boolean Result of insert or update function
+ * @access private
+ */
+ private function _processData(
+ PDO $dbh,
+ array $values,
+ Toolkit_Coupons_CouponFactory $cFactory
+ ) {
+ unset($values['MAX_FILE_SIZE']);
+ $deleteImage = ($_POST['del_image_rmv']) ? true: false;
+ foreach ($values as $k => $v) {
+ if ( $k != 'uploaded_file_rmv'
+ && preg_match('/^.+_rmv$/', $k)
+ ) {
+ unset($values[$k]);
+ }
+ }
+
+ $sdateStr = implode('/', $values['sdate']);
+ $sdateTS = strtotime($sdateStr);
+ $sdate = new Date();
+ $sdate->setDate($sdateTS, DATE_FORMAT_TIMESTAMP);
+ $values['sdate'] = $sdate;
+
+ $edateStr = implode('/', $values['edate']);
+ $edateTS = strtotime($edateStr);
+ $edate = new Date();
+ $edate->setDate($edateTS, DATE_FORMAT_TIMESTAMP);
+ $values['edate'] = $edate;
+
+ $exdateStr = implode('/', $values['expiration']);
+ $exdateTS = strtotime($exdateStr);
+ $exdate = new Date();
+ $exdate->setDate($exdateTS, DATE_FORMAT_TIMESTAMP);
+ $values['expiration'] = $exdate;
+ if ($deleteImage) {
+ $values['image'] = null;
+ } else {
+ $values['image'] = Toolkit_Coupons_ImageFactory::getImage($values);
+ }
+
+ //echo '<pre>'.print_r($values, true).'</pre>';
+ if (ctype_digit((string)$_GET['id'])) {
+ // Editing a banner
+ $coupon = $cFactory->fetch($dbh, $_GET['id']);
+ } else {
+ $coupon = $cFactory->createCoupon($values);
+ }
+
+
+ return ctype_digit($_GET['id'])
+ ? $coupon->update($dbh, $values)
+ : $coupon->save($dbh);
+ }
+
+ // }}}
+
+ // {{{ sendCouponToImageServer()
+
+ /**
+ * Send a coupon image to the image server
+ *
+ * Sets the image name in the submit values, so when saving
+ * the banner, we keep the image that was uploaded.
+ *
+ * Injects the thumbnail image of this uploaded coupon into
+ * the form, this way if validation fails, the thumbnail will
+ * be shown on the form so the user knows they don't have to
+ * re-upload the coupon.
+ *
+ * @param Toolkit_Image_Server $is Image server
+ * @param string $file key of upload in $_FILES super array
+ *
+ * @return void
+ * @access protected
+ */
+ protected function sendCouponToImageServer(
+ Toolkit_Image_Server $is,
+ $file
+ ) {
+ $oldCoupon = $this->getSubmitValue('image');
+ if (!empty($oldCoupon)) {
+ $is->imageDelete($oldCoupon);
+ }
+
+ $imgTag = '<img src="%s%s">';
+ $name = $is->imageUpload($file);
+
+ $htmlImg = sprintf($imgTag, COUPON_THUMB, $name);
+
+ $currImg = $this->getElement('current_image_rmv');
+ $currImg->setValue($htmlImg);
+
+ $fileName = $this->getElement('image');
+ $fileName->setValue($name);
+ $this->_submitValues['image'] = $name;
+ }
+
+ // }}}
+ // {{{ setupRenderers()
+ // @codeCoverageIgnoreStart
+
+ /**
+ * Custom rendering templates for special fields on the form
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ parent::setupRenderers();
+ $renderer = $this->defaultRenderer();
+ $required
+ = "<!-- BEGIN required -->\n
+ <span class=\"req\"> * </span>\n
+ <!-- END required -->";
+ $error
+ = "<!-- BEGIN error -->\n
+ <div class=\"req\"> {error} </div>\n
+ <!-- END error -->";
+ $renderer->setElementTemplate(
+ "<tr>\n
+ <td colspan=\"2\">$required{label}$error{element}</td>\n
+ </tr>",
+ 'description'
+ );
+ $renderer->setElementTemplate(
+ "<tr align=\"center\">\n
+ <td colspan=\"2\">$required{label}$error{element}</td>\n
+ </tr>",
+ 'submit_rmv'
+ );
+ $renderer->setElementTemplate(
+ "<tr align=\"center\">\n
+ <td colspan=\"2\">$required{label}$error{element}</td>\n
+ </tr>",
+ 'delete_rmv'
+ );
+
+ }
+
+ // @codeCoverageIgnoreEnd
+ // }}}
+
+ // {{{ toHtml()
+
+ /**
+ * Call the rendering function to get the form in a string
+ *
+ * @param PDO $dbh Database handler
+ * @param Toolkit_Image_Server $is Image Server
+ * @param Toolkit_Coupons_CouponFactory $cFactory Coupon Factory
+ *
+ * @return string $output The Form to be rendered or success msg.
+ * @access protected
+ */
+ public function toHtml(
+ PDO $dbh,
+ Toolkit_Image_Server $is,
+ Toolkit_Coupons_CouponFactory $cFactory
+ ) {
+ $GLOBALS['styleSheets'][] = MEDIA_BASE_URL . 'css/contactform.css';
+ $GLOBALS['bottomScripts'][] = MEDIA_APP_BASE_URL . 'libjs/textlimit.js';
+ $GLOBALS['bottomScripts'][] = MEDIA_BASE_URL . 'libjs/couponLimitText.js';
+
+ // Handle Deleting banner.
+ if ( $this->isSubmitted()
+ && ctype_digit($_GET['id'])
+ ) {
+ if ($this->getSubmitValue('delete_rmv')) {
+ $coupon = $cFactory->fetch($dbh, $_GET['id']);
+ if ($coupon instanceof Toolkit_Coupons_Coupon) {
+ if ($coupon->delete($dbh, $is)) {
+ return 'Coupon successfully deleted.';
+ }
+ } else {
+ // the coupon has already been deleted or doesn't exist.
+ return "The coupon has already been deleted or doesn't exists.";
+ }
+ }
+ }
+
+ $this->setupRenderers();
+ $uploadedNewCouponImg
+ = ( $this->isSubmitted()
+ && is_uploaded_file($_FILES['file_rmv']['tmp_name'])
+ );
+ if ($_POST['del_image_rmv'] && $_POST['old_image_rmv']) {
+ $is->imageDelete($_POST['old_image_rmv']);
+ }
+ if ($uploadedNewCouponImg) {
+ $this->sendCouponToImageServer($is, 'file_rmv');
+ }
+ if ($this->validate()) {
+ $this->cleanForm();
+
+ $submitValues = $this->getSubmitValues();
+ if ($this->_processData($dbh, $submitValues, $cFactory)) {
+ $this->freeze();
+ $output = $this->successMsg;
+ }
+ } elseif ($this->isSubmitted()) {
+ $output = $this->errorMsg;
+ $output .= parent::toHTML();
+ } else {
+ $output = parent::toHTML();
+ }
+ return $output;
+ }
+
+ // }}}
+}
--- /dev/null
+<?php
+// vim:set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker syntax=php:
+
+/**
+ * Coupons search form
+ *
+ * PHP version 5
+ *
+ * @category Coupons
+ * @package Toolkit_Coupons
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: AdminSearch.php,v 1.2 2010/08/12 18:07:21 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Coupons search form
+ *
+ * @category Coupons
+ * @package Toolkit_Coupons
+ * @author Jamie Kahgee <jamie@gaslightmedia.com>
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @link <>
+ */
+class Toolkit_Coupons_AdminSearch extends Toolkit_FormBuilder
+{
+ // {{{ properties
+
+ /**
+ * 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.
+ *
+ * @var string
+ * @access protected
+ */
+ protected $registeredRules = array();
+
+ // }}}
+
+ // {{{ configureConstants()
+
+
+ /**
+ * Configure constant form values
+ *
+ * @return void
+ * @access public
+ */
+ public function configureConstants()
+ {
+ $c = array(
+ 'action' => 'list',
+ );
+
+ $this->setupConstants($c);
+ }
+
+ // }}}
+ // {{{ configureElements()
+
+
+ /**
+ * Configure the elements that should be on the form
+ *
+ * @param PDO $dbh Database handler
+ * @param Config_Container $c Application configuration
+ *
+ * @return void
+ * @access public
+ */
+ public function configureElements(PDO $dbh, Config_Container $c)
+ {
+ $e = array();
+
+ $appName =& $c->getItem('section', 'conf')
+ ->getItem('directive', 'applicationName')
+ ->getContent();
+
+ if (defined("MEMBERS_DB") && MEMBERS_DB) {
+ $memberConf = new Config;
+ $memberRoot =& $memberConf->parseConfig(
+ BASE . 'Toolkit/Members/config.ini',
+ 'IniFile'
+ );
+ $memberSing = $memberRoot->getItem('section', 'listing type')
+ ->getItem('directive', 'singular')
+ ->getContent();
+ }
+
+ $categories = $this->_getCategories($dbh);
+ if (defined("MEMBERS_DB") && MEMBERS_DB) {
+ $members = $this->_getMembers($dbh);
+ }
+ // All Grouped Elements are created here.
+
+ // All Elements are created here. This includes group element definitions.
+ $e[] = array(
+ 'type' => 'hidden',
+ 'req' => false,
+ 'name' => 'page',
+ );
+ $e[] = array(
+ 'type' => 'hidden',
+ 'req' => false,
+ 'name' => 'module',
+ );
+ $e[] = array(
+ 'type' => 'header',
+ 'req' => false,
+ 'name' => 'categoryInfoHdr',
+ 'display' => "$appName Search"
+ );
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => false,
+ 'name' => 'title',
+ 'display' => 'Title'
+ );
+ $e[] = array(
+ 'type' => 'select',
+ 'req' => false,
+ 'name' => 'category',
+ 'display' => 'Category',
+ 'opts' => array(
+ '' => '-- Select --'
+ ) + $categories
+ );
+ $e[] = array(
+ 'type' => 'select',
+ 'req' => false,
+ 'name' => 'status',
+ 'display' => 'Status',
+ 'opts' => array(
+ '' => '-- Select --',
+ 'active' => 'Active',
+ 'pending' => 'Pending',
+ 'expired' => 'Expired'
+ )
+ );
+ if (defined("MEMBERS_DB") && MEMBERS_DB) {
+ $e[] = array(
+ 'type' => 'select',
+ 'req' => false,
+ 'name' => 'member',
+ 'display' => $memberSing,
+ 'opts' => array(
+ '' => '-- Select --'
+ ) + $members
+ );
+ }
+ $e[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'submit',
+ 'display' => 'Search'
+ );
+
+ $this->setupElements($e);
+ }
+
+ // }}}
+ // {{{ configureFilters()
+
+
+ /**
+ * Sets up filters for form elements
+ *
+ * These filters will be run before the rules are checked
+ * against the elements
+ *
+ * @return void
+ * @access public
+ */
+ public function configureFilters()
+ {
+ $f = array();
+ $f[] = array(
+ 'element' => '__ALL__',
+ 'filter' => 'trim'
+ );
+
+ $this->setupFilters($f);
+ }
+
+ // }}}
+ // {{{ configureForm()
+
+
+ /**
+ * Configures the entire form so it can be rendered
+ *
+ * @param PDO $dbh Database handler
+ * @param Config_Container $c Application configuration
+ *
+ * @return void
+ * @access public
+ */
+ public function configureForm(PDO $dbh, Config_Container $c)
+ {
+ $this->configureElements($dbh, $c);
+ $this->configureFilters();
+ $this->configureRules();
+ $this->configureConstants();
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+
+ /**
+ * Defines rules for the forms elements
+ *
+ * @return void
+ * @access public
+ */
+ public function configureRules()
+ {
+ $r = array();
+ $this->setupRules($r);
+ }
+
+ // }}}
+
+ // {{{ _getCategories()
+
+ /**
+ * Get the coupon categories available
+ *
+ * @param PDO $dbh Database handler
+ *
+ * @return array coupon categories
+ * @access private
+ */
+ private function _getCategories(PDO $dbh)
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM coupon_category
+ ORDER BY name";
+
+ $categories = array();
+ foreach ($dbh->query($sql, PDO::FETCH_ASSOC) as $row) {
+ $categories[$row['name']] = $row['name'];
+ }
+
+ return $categories;
+ } catch (PDOException $e) {
+ Toolkit_Logger::logException('DB Error', $e);
+ throw new Toolkit_Coupons_Exception('Error retrieving categories');
+ }
+ }
+
+ // }}}
+ // {{{ _getMembers()
+
+ /**
+ * Get members that have coupons available
+ *
+ * @param PDO $dbh Database handler
+ *
+ * @return array members with coupons
+ * @access private
+ */
+ private function _getMembers(PDO $dbh)
+ {
+ try {
+ $sql = "
+ SELECT m.member_id, m.member_name
+ FROM coupons c
+ JOIN member m
+ ON c.member = m.member_id
+ ORDER BY member_name";
+
+ $members = array();
+ foreach ($dbh->query($sql, PDO::FETCH_ASSOC) as $row) {
+ $members[$row['member_id']] = $row['member_name'];
+ }
+
+ return $members;
+ } catch (PDOException $e) {
+ Toolkit_Logger::logException('DB Error', $e);
+ throw new Toolkit_Coupons_Exception('Error retrieving categories');
+ }
+ }
+
+ // }}}
+
+ // {{{ setupRenderers()
+
+
+ /**
+ * Sets up renderers for the forms elements
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ parent::setupRenderers();
+ $renderer =& $this->defaultRenderer();
+ $tpl = '<tr align="center"><td colspan="2">{element}</td></tr>';
+ $renderer->setElementTemplate($tpl, 'submit');
+ }
+
+ // }}}
+
+ // {{{ toHtml()
+
+ /**
+ * Call the rendering function to get the form in a string
+ *
+ * @return string $output The Form to be rendered or success msg.
+ * @access public
+ */
+ public function toHtml()
+ {
+ $GLOBALS['styleSheets'][] = MEDIA_BASE_URL . 'css/contactform.css';
+ $this->setupRenderers();
+ $output = '';
+ if (!$this->validate() && $this->isSubmitted()) {
+ $output = $this->errorMsg;
+ }
+
+ $output .= parent::toHTML();
+ return $output;
+ }
+
+ // }}}
+}
+?>
--- /dev/null
+<?php
+// vim:set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker syntax=php:
+
+/**
+ * Lists coupons in a datagrid
+ *
+ * PHP version 5
+ *
+ * @category Coupons
+ * @package Toolkit_Coupons
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: CategoriesDataGrid.php,v 1.1 2010/02/12 21:16:32 jamie Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * List the coupons in the database in a datagrid
+ *
+ * Handles listing of the coupons in the couponDB, pagnation, and sorting.
+ * Also controls the resulting number of coupons that are rendered
+ * on the page.
+ *
+ * @category Coupons
+ * @package Toolkit_Coupons
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit_DataGridBuilder
+ */
+class Toolkit_Coupons_CategoriesDataGrid extends Toolkit_DataGridBuilder
+{
+ // {{{ properties
+
+ /**
+ * Description for protected
+ * @var string
+ * @access protected
+ */
+ protected $noRecMessage = 'No Categories Found.';
+
+ // }}}
+
+ // {{{ configureColumns()
+
+ /**
+ * Configure the columns for the datagrid
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureColumns()
+ {
+ $edit = new Structures_DataGrid_Column(
+ 'Edit',
+ null,
+ null,
+ array('class' => 'editLink'),
+ null,
+ array(&$this, 'renderEditLink')
+ );
+ $this->addColumn($edit);
+
+ $category = new Structures_DataGrid_Column(
+ 'Category',
+ 'name',
+ 'name'
+ );
+ $this->addColumn($category);
+ }
+
+ // }}}
+
+ // {{{ renderEditLink()
+
+ /**
+ * Render the edit link for a category
+ *
+ * @param array $data DB record
+ *
+ * @return mixed Link to edit a category
+ * @access public
+ */
+ public function renderEditLink($data)
+ {
+ extract($data['record']);
+ $link = '<a href="%sadmin/coupons.php?page=editCategory&module=editCategory&id=%s">Edit</a>';
+ return sprintf($link, MEDIA_BASE_URL, $id);
+ }
+
+ // }}}
+
+ // {{{ setQuery()
+
+ /**
+ * Short description for function
+ *
+ * @return void
+ * @access public
+ */
+ public function setQuery()
+ {
+ $sql = "
+ SELECT *
+ FROM coupon_category";
+
+ parent::setQuery($sql);
+ }
+
+ // }}}
+
+ // {{{ toHtml()
+
+ public function toHtml()
+ {
+ $GLOBALS['styleSheets'][] = MEDIA_BASE_URL . 'Toolkit/Coupons/styles.css';
+ return parent::toHTML();
+ }
+
+ // }}}
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Coupon Category class
+ *
+ * Create/Update a category
+ *
+ * PHP version 5
+ *
+ * @category Toolkit_Coupons
+ * @package Coupons
+ * @author Jamie Kahgee <jamie@gaslightmedia.com>
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version CVS: $Id: Category.php,v 1.2 2010/02/12 21:16:32 jamie Exp $
+ * @link <>
+ * @see References to other sections (if any)...
+ */
+
+/**
+ * Coupon Category class
+ *
+ * Create/Update a category
+ *
+ * @category Toolkit_Coupons
+ * @package Coupons
+ * @author Jamie Kahgee <jamie@gaslightmedia.com>
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version Release: @package_version@
+ * @link <>
+ * @see References to other sections (if any)...
+ */
+class Toolkit_Coupons_Category
+{
+ // {{{ properties
+
+ /**
+ * Category name
+ * @var string
+ * @access private
+ */
+ private $_name;
+ private $_id;
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * @param string $name New category name
+ *
+ * @return void
+ * @access public
+ */
+ public function __construct($name, $id = null)
+ {
+ $this->_name = $name;
+ if (ctype_digit((string)$id)) {
+ settype($id, 'int');
+ $this->_id = $id;
+ }
+ }
+
+ // }}}
+
+ // {{{ delete()
+
+ public function delete(PDO $dbh)
+ {
+ try {
+ if (empty($this->_name)) {
+ throw new RuntimeException('category not set');
+ }
+
+ $sql = "
+ DELETE FROM coupon_category
+ WHERE name = :name";
+
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(':name', $this->_name, PDO::PARAM_INT);
+ $res = $stmt->execute();
+ return $res;
+ } catch (PDOException $e) {
+ Toolkit_Logger::logException('DB Error', $e);
+ throw new Toolkit_Coupons_Exception('error deleting category');
+ } catch (RuntimeException $e) {
+ Toolkit_Logger::logException('Runtime Error', $e);
+ throw new Toolkit_Coupons_Exception('category not set');
+ }
+ }
+
+ // }}}
+
+ // {{{ &fetch()
+
+ /**
+ * Fetch an instance of a category by db id
+ *
+ * @param PDO $dbh Database handler
+ * @param integer $id ID of category to fetch
+ *
+ * @returns Toolkit_Coupons_Category concrete category
+ * @throws Toolkit_Coupons_Exception on invalid argument or pdo exception
+ * @access public
+ * @static
+ */
+ public static function &fetch(PDO $dbh, $id)
+ {
+ try {
+ if (!ctype_digit((string)$id)) {
+ throw new InvalidArgumentException(
+ "\$id must be an integer [$id] given"
+ );
+ }
+ $sql = "
+ SELECT *
+ FROM coupon_category
+ WHERE id = :id";
+
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(':id', $id, PDO::PARAM_INT);
+ $stmt->execute();
+
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ return new self($row['name'], $row['id']);
+ } catch (InvalidArgumentException $e) {
+ Toolkit_Logger::logException('Invalid Arg', $e);
+ throw new Toolkit_Coupons_Exception('Error fetching coupon');
+ } catch (PDOException $e) {
+ Toolkit_Logger::logException('DB Error', $e);
+ throw new Toolkit_Coupons_Exception('Error fetching coupon');
+ }
+ }
+
+ // }}}
+
+ // {{{ getName()
+
+ /**
+ * Get the category name
+ *
+ * @return string category name
+ *
+ * @access public
+ */
+ public function getName()
+ {
+ return $this->_name;
+ }
+
+ // }}}
+
+ // {{{ save()
+
+ /**
+ * Save a category to the DB
+ *
+ * @param PDO $dbh Database handler to use
+ *
+ * @return boolean result of save
+ * @throws Toolkit_Coupons_Exception
+ * @access public
+ */
+ public function save(PDO $dbh)
+ {
+ $classData = array(
+ 'name' => $this->_name
+ );
+
+ $sql = Toolkit_Common::createSQLInsert(
+ 'coupon_category',
+ array_keys($classData)
+ );
+
+ try {
+ $dbh->beginTransaction();
+ $stmt = Toolkit_Common::prepareQuery(
+ $dbh,
+ 'coupon_category',
+ $sql,
+ $classData
+ );
+ $stmt->execute();
+
+ $sql = "
+ SELECT id
+ FROM coupon_category
+ ORDER BY id DESC LIMIT 1";
+ $row = $dbh->query($sql)->fetch();
+
+ $dbh->commit();
+ $this->_id = $row['id'];
+
+ settype($this->_id, 'int');
+
+ return $this->_id;
+ } catch (PDOException $e) {
+ $dbh->rollback();
+ Toolkit_Logger::logException('DB Error', $e);
+ throw new Toolkit_Coupons_Exception('Error Saving Category');
+ }
+ }
+
+ // }}}
+ // {{{ setName()
+
+ /**
+ * set a new name for a category
+ *
+ * @param string $name New category name
+ *
+ * @return void
+ * @access public
+ */
+ public function setName($name)
+ {
+ $this->_name = $name;
+ }
+
+ // }}}
+
+ // {{{ update()
+
+ /**
+ * Update a category in the database
+ *
+ * @param PDO $dbh Database handler to use
+ *
+ * @return boolean result of update query
+ * @throws Toolkit_Coupons_Exception
+ * @access public
+ */
+ public function update(PDO $dbh)
+ {
+ try {
+ if (!is_int($this->_id)) {
+ throw new RuntimeException('category not set');
+ }
+ $classData = array(
+ 'name' => $this->_name
+ );
+
+ $sql = Toolkit_Common::createSQLUpdate(
+ 'coupon_category',
+ array_keys($classData),
+ array('id= :id')
+ );
+
+ $classData['id'] = $this->_id;
+ $stmt = Toolkit_Common::prepareQuery(
+ $dbh,
+ 'coupon_category',
+ $sql,
+ $classData
+ );
+ $res = $stmt->execute();
+ return $res;
+ } catch (PDOException $e) {
+ Toolkit_Logger::logException('DB Error', $e);
+ throw new Toolkit_Coupons_Exception('error updating category');
+ } catch (RuntimeException $e) {
+ Toolkit_Logger::logException('Runtime Error', $e);
+ throw new Toolkit_Coupons_Exception('category not set');
+ }
+ }
+
+ // }}}
+}
+?>
--- /dev/null
+
+<?php
+// vim:set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker syntax=php:
+
+/**
+ * File Doc Comment
+ *
+ * PHP version 5
+ *
+ * @category Coupons
+ * @package Toolkit_Coupons
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: CategorySelectForm.php,v 1.1 2010/02/12 21:16:32 jamie Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Coupon Category form
+ *
+ * Manages the creation and editing form for manipulating coupon categories
+ *
+ * @category Coupons
+ * @package Toolkit_Coupons
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Coupons_CategorySelectForm extends Toolkit_FormBuilder
+{
+ // {{{ properties
+
+ /**
+ * Success msg if the form validates successfully
+ *
+ * @var string
+ * @access protected
+ */
+ protected $successMsg = '';
+
+ /**
+ * 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.
+ *
+ * @var string
+ * @access protected
+ */
+ protected $registeredRules = array();
+
+ // }}}
+
+ // {{{ configureElements()
+
+ /**
+ * Configure how the form elements should look
+ *
+ * @return void
+ * @access public
+ */
+ public function configureElements()
+ {
+ $e = array();
+
+ // All Grouped Elements are created here.
+
+ // All Elements are created here. This includes group element definitions.
+ $e[] = array(
+ 'type' => 'select',
+ 'req' => false,
+ 'name' => 'name',
+ 'display' => 'Category',
+ 'opts' => array('class' => 'text')
+ );
+ $e[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'submit',
+ 'display' => 'Search',
+ 'opts' => array('id' => 'submit')
+ );
+
+ $this->setupElements($e);
+ }
+
+ // }}}
+ // {{{ configureFilters()
+
+ /**
+ * Configure how the form elements should act when being submitted
+ *
+ * @return void
+ * @access protected
+ */
+ public function configureFilters()
+ {
+ $f = array();
+ $f[] = array(
+ 'element' => '__ALL__',
+ 'filter' => 'trim'
+ );
+
+ $this->setupFilters($f);
+ }
+
+ // }}}
+ // {{{ configureForm()
+
+ /**
+ * Configure a form so we can use it
+ *
+ * @return void
+ * @access public
+ */
+ public function configureForm()
+ {
+ $this->configureElements();
+ $this->configureFilters();
+ $this->configureRules();
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Configure how the form elements should act
+ *
+ * @return void
+ * @access public
+ */
+ public function configureRules()
+ {
+ $r = array();
+
+ $this->setupRules($r);
+ }
+
+ // }}}
+
+ // {{{ _processData()
+
+ /**
+ * Determine how the form should be handled (insert new data or update old)
+ *
+ * @param PDO $dbh Database handler
+ * @param array $values Submitted form values
+ *
+ * @return boolean Result of insert or update function
+ * @access private
+ */
+ private function _processData(PDO $dbh, array $values)
+ {
+ $category = new Toolkit_Coupons_Category($values['name']);
+
+ return ctype_digit($_GET['id'])
+ ? $category->update($dbh, $_GET['id'])
+ : $category->save($dbh);
+ }
+
+ // }}}
+
+ // {{{ setupRenderers()
+ // @codeCoverageIgnoreStart
+
+ /**
+ * Custom rendering templates for special fields on the form
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ parent::setupRenderers();
+ $renderer =& $this->defaultRenderer();
+ $required
+ = "<!-- BEGIN required -->\n
+ <span class=\"req\"> * </span>\n
+ <!-- END required -->";
+ $error
+ = "<!-- BEGIN error -->\n
+ <div class=\"req\"> {error} </div>\n
+ <!-- END error -->";
+ $renderer->setElementTemplate(
+ "<tr align=\"center\">\n
+ <td colspan=\"2\">$required{label}$error{element}</td>\n
+ </tr>",
+ 'submit'
+ );
+ $renderer->setElementTemplate(
+ "<tr align=\"center\">\n
+ <td colspan=\"2\">$required{label}$error{element}</td>\n
+ </tr>",
+ 'delete'
+ );
+
+ }
+
+ // @codeCoverageIgnoreEnd
+ // }}}
+
+ // {{{ toHtml()
+
+ /**
+ * Call the rendering function to get the form in a string
+ *
+ * @param PDO $dbh Database handler
+ *
+ * @return string $output The Form to be rendered or success msg.
+ * @access protected
+ */
+ public function toHtml(PDO $dbh)
+ {
+ $GLOBALS['styleSheets'][] = MEDIA_BASE_URL . 'css/contactform.css';
+
+ $this->setupRenderers();
+ if ($this->validate()) {
+ $this->cleanForm();
+
+ if ($this->_processData($dbh, $this->getSubmitValues())) {
+ $this->freeze();
+ $output = $this->successMsg;
+ }
+ }
+ $output .= parent::toHTML();
+ return $output;
+ }
+
+ // }}}
+}
+?>
--- /dev/null
+<?php
+class Toolkit_Coupons_Controller
+{
+ // {{{ getFlexyOptions()
+ public static function getFlexyOptions()
+ {
+ $options = $GLOBALS['flexyOptions'];
+ $options['templateDir']
+ = dirname(__FILE__) . '/templates';
+ $options['compileDir']
+ = dirname(__FILE__) . '/templates/compiled';
+
+ return $options;
+ }
+
+ // }}}
+
+ // {{{ toHtml()
+ public function toHtml(PDO $dbh, Config_Container $appConf)
+ {
+ switch ($_GET['module']) {
+ case 'editCoupon' :
+ if (defined('MEMBERS_DB') && MEMBERS_DB) {
+ $cFactory = new Toolkit_Coupons_MemberCouponFactory();
+ } else {
+ $cFactory = new Toolkit_Coupons_WebCouponFactory();
+ }
+ $tFactory = new Toolkit_Coupons_ThumbnailFactory();
+ $form = new Toolkit_Coupons_AdminEditCouponForm('edit_coupon');
+ $form->configureForm($dbh, $appConf, $tFactory, $cFactory);
+ $ret = $form->toHtml($dbh, new Toolkit_Image_Server(), $cFactory);
+ break;
+
+ case 'editCategory' :
+ $form = new Toolkit_Coupons_AdminEditCategoryForm('edit_category');
+ $form->configureForm($dbh);
+ $ret = $form->toHtml($dbh);
+ break;
+
+ case 'listCategories' :
+ $categories = new Toolkit_Coupons_CategoriesDataGrid($dbh);
+ $categories->setQuery();
+ $categories->setDefaultSort(array('name' => 'ASC'));
+ $ret = $categories->toHtml();
+ break;
+
+ case 'listCoupons' :
+ default :
+ $search = new Toolkit_Coupons_AdminSearch(
+ 'search_form',
+ 'get',
+ MEDIA_BASE_URL . 'admin/coupons.php',
+ '',
+ null,
+ true
+ );
+ $search->configureForm($dbh, $appConf);
+ $ret = $search->toHtml();
+
+ $coupons = new Toolkit_Coupons_CouponsDataGrid($dbh);
+ $coupons->setQuery();
+ if (defined("MEMBER_DB") && MEMBER_DB) {
+ $coupons->setDefaultSort(array('member_name' => 'ASC'));
+ } else {
+ $coupons->setDefaultSort(array('category_name' => 'ASC'));
+ }
+ $ret .= $coupons->toHtml();
+ break;
+ }
+
+ return $ret;
+ }
+
+ // }}}
+}
+?>
--- /dev/null
+<?php
+class Toolkit_Coupons_Coupon
+{
+ // {{{ properties
+ protected $title;
+ protected $description;
+ protected $image;
+ protected $expiration;
+
+ // }}}
+
+ // {{{ __construct()
+ public function __construct(array $data)
+ {
+ if (!isset($data['title'])) {
+ throw new BadMethodCallException('Missing title');
+ }
+
+ $this->title = $data['title'];
+ $this->description = $data['description'];
+
+ if (isset($data['image']) && !empty($data['image'])) {
+ if (!($data['image'] instanceof Toolkit_Coupons_Image)) {
+ throw new InvalidArgumentException(
+ 'image must be of type Toolkit_Coupons_Image'
+ );
+ }
+ $this->image = $data['image'];
+ }
+ if (isset($data['expiration']) && !empty($data['expiration'])) {
+ if (!($data['expiration'] instanceof Date)) {
+ throw new InvalidArgumentException(
+ 'expiration must be of type Date'
+ );
+ }
+ $this->expiration = $data['expiration'];
+ }
+ }
+
+ // }}}
+
+ // {{{ getDescription()
+ public function getDescription()
+ {
+ return $this->description;
+ }
+
+ // }}}
+ // {{{ getExpiration()
+ public function getExpiration()
+ {
+ return $this->expiration;
+ }
+
+ // }}}
+ // {{{ getImage()
+ public function getImage()
+ {
+ return $this->image;
+ }
+
+ // }}}
+ // {{{ getTitle()
+ public function getTitle()
+ {
+ return $this->title;
+ }
+
+ // }}}
+
+ // {{{ setDescription()
+ public function setDescription($description)
+ {
+ $this->description = $description;
+ }
+
+ // }}}
+ // {{{ setExpiration()
+ public function setExpiration(Date $expiration)
+ {
+ $this->expiration = $expiration;
+ }
+
+ // }}}
+ // {{{ setImage()
+ public function setImage(Toolkit_Coupons_Image $image = null)
+ {
+ $this->image = $image;
+ }
+
+ // }}}
+ // {{{ setTitle()
+ public function setTitle($title)
+ {
+ $this->title = $title;
+ }
+
+ // }}}
+
+ // {{{ update()
+ public function update(array $data)
+ {
+ if (isset($data['title'])) {
+ $this->setTitle($data['title']);
+ }
+
+ if (isset($data['description'])) {
+ $this->setDescription($data['description']);
+ }
+
+ if (isset($data['image'])) {
+ if ($data['image'] instanceof Toolkit_Coupons_Image) {
+ $this->setImage($data['image']);
+ }
+ }
+
+ if (isset($data['expiration'])) {
+ if ($data['expiration'] instanceof Date) {
+ $this->setExpiration($data['expiration']);
+ }
+ }
+ }
+
+ // }}}
+}
--- /dev/null
+<?php
+
+class Toolkit_Coupons_CouponFactory {}
+?>
--- /dev/null
+<?php
+class Toolkit_Coupons_Coupons implements Toolkit_Coupons_IHtmlElement
+{
+ // {{{ properties
+ private $_coupons = array();
+
+ // }}}
+ // {{{ __toString()
+ // @codeCoverageIgnoreStart
+
+ public function __toString()
+ {
+ ksort($this->_coupons);
+ $html = '';
+ foreach ($this->_coupons as $i => $j) {
+ $html .= "<h2>$i</h2>";
+ $k = 0;
+ $length = count($j);
+ $html .= '<div class="couponcontainer">';
+ $open = true; // need to close container at end.
+ while ($c = $this->_coupons[$i][$k]) {
+ $html .= (string) $c;
+ if ($k % 2) {
+ $open = false; // don't close container at end.
+ $html .= '</div>';
+ if ($k < $length - 1) { // if we have at least one more
+ $open = true; // close container at end.
+ $html .= '<div class="couponcontainer">';
+ }
+ }
+ ++$k;
+ }
+ if ($open) {
+ $html .= '</div>';
+ }
+ }
+
+ return $html;
+ }
+
+ // @codeCoverageIgnoreEnd
+ // }}}
+
+ // {{{ addCoupon()
+
+ public function addCoupon(Toolkit_Coupons_Coupon $coupon)
+ {
+ $cat = $coupon->getCategory();
+ $this->_coupons[$cat][] = $coupon;
+ }
+
+ // }}}
+}
+?>
--- /dev/null
+<?php
+// vim:set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker syntax=php:
+
+/**
+ * Lists coupons in a datagrid
+ *
+ * PHP version 5
+ *
+ * @category Coupons
+ * @package Toolkit_Coupons
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: CouponsDataGrid.php,v 1.2 2010/08/12 18:07:21 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * List the coupons in the database in a datagrid
+ *
+ * Handles listing of the coupons in the couponDB, pagnation, and sorting.
+ * Also controls the resulting number of coupons that are rendered
+ * on the page.
+ *
+ * @category Coupons
+ * @package Toolkit_Coupons
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @copyright 2008 Gaslight Media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit_DataGridBuilder
+ */
+class Toolkit_Coupons_CouponsDataGrid extends Toolkit_DataGridBuilder
+{
+ // {{{ properties
+
+ /**
+ * Description for protected
+ * @var string
+ * @access protected
+ */
+ protected $noRecMessage = 'No Coupons Found.';
+
+ // }}}
+
+ // {{{ configureColumns()
+
+ /**
+ * Configure the columns for the datagrid
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureColumns()
+ {
+ $edit = new Structures_DataGrid_Column(
+ 'Edit',
+ null,
+ null,
+ array('class' => 'editLink'),
+ null,
+ array(&$this, 'renderEditLink')
+ );
+ $this->addColumn($edit);
+
+ $title = new Structures_DataGrid_Column(
+ 'Title',
+ 'title',
+ 'title'
+ );
+ $this->addColumn($title);
+
+ $category = new Structures_DataGrid_Column(
+ 'Category',
+ 'category_name',
+ 'category_name'
+ );
+ $this->addColumn($category);
+
+ if (defined("MEMBER_DB") && MEMBER_DB) {
+ $member = new Structures_DataGrid_Column(
+ 'Member',
+ 'member_name',
+ 'member_name'
+ );
+ $this->addColumn($member);
+ }
+
+ $sdate = new Structures_DataGrid_Column(
+ 'Starts',
+ 'sdate',
+ 'edate'
+ );
+ $this->addColumn($sdate);
+
+ $edate = new Structures_DataGrid_Column(
+ 'Ends',
+ 'edate',
+ 'edate'
+ );
+ $this->addColumn($edate);
+
+ $expires = new Structures_DataGrid_Column(
+ 'Expires',
+ 'expiration',
+ 'expiration'
+ );
+ $this->addColumn($expires);
+ }
+
+ // }}}
+
+ // {{{ renderEditLink()
+
+ /**
+ * Render the edit link for a category
+ *
+ * @param array $data DB record
+ *
+ * @return mixed Link to edit a category
+ * @access public
+ */
+ public function renderEditLink($data)
+ {
+ extract($data['record']);
+ $link = '<a href="%sadmin/coupons.php?page=editCoupon&module=editCoupon&id=%s">Edit</a>';
+ return sprintf($link, MEDIA_BASE_URL, $id);
+ }
+
+ // }}}
+
+ // {{{ setQuery()
+
+ /**
+ * Short description for function
+ *
+ * @return void
+ * @access public
+ */
+ public function setQuery()
+ {
+ if (defined("MEMBER_DB") && MEMBER_DB) {
+ $sql = "
+ SELECT c.id, c.title, cc.name AS category_name, m.member_name,
+ c.sdate, c.edate, c.expiration
+ FROM coupons c
+ LEFT JOIN coupon_category cc
+ ON c.category = cc.name
+ LEFT JOIN member m
+ ON c.member = m.member_id";
+ } else {
+ $sql = "
+ SELECT c.id, c.title, cc.name AS category_name,
+ c.sdate, c.edate, c.expiration
+ FROM coupons c
+ LEFT JOIN coupon_category cc
+ ON c.category = cc.name";
+ }
+
+ $params = array();
+ if (!empty($_GET['title'])) {
+ $business = preg_replace('/\W/', '', urldecode($_GET['title']));
+ $params[] = "regexp_replace(title, '[^[:alnum:]]', '', 'g') ~* " .
+ $this->options['dbc']->quote($business);
+ }
+ if ($memberId = filter_input(INPUT_GET, 'member', FILTER_VALIDATE_INT)) {
+ $params[] = 'member = ' .
+ $this->options['dbc']->quote($memberId);
+ }
+ if (!empty($_GET['category'])) {
+ $params[] = 'category = ' .
+ $this->options['dbc']->quote($_GET['category']);
+ }
+ if ($status = filter_input(INPUT_GET, 'status')) {
+ switch (strtolower($status)) {
+ case 'active' :
+ $params[] = 'active = true';
+ $params[] = 'current_date between sdate and edate';
+ break;
+
+ case 'pending' :
+ $params[] = 'pending = true';
+ break;
+
+ case 'expired' :
+ $params[] = 'current_date > edate';
+ break;
+ }
+ }
+ if ( ctype_digit((string)$_GET['sdate']['m'])
+ && ctype_digit((string)$_GET['sdate']['d'])
+ && ctype_digit((string)$_GET['sdate']['Y'])
+ ) {
+ $params[] = 'sdate >= ' .
+ $this->options['dbc']->quote(implode('/', $_GET['sdate']));
+ }
+ if ( ctype_digit((string)$_GET['edate']['m'])
+ && ctype_digit((string)$_GET['edate']['d'])
+ && ctype_digit((string)$_GET['edate']['Y'])
+ ) {
+ $params[] = 'edate <= ' .
+ $this->options['dbc']->quote(implode('/', $_GET['edate'])) . ' OR edate IS NULL';
+ }
+
+ if (isset($_GET['_qf__search_form']) && !empty($params)) {
+ $params = implode(' AND ', $params);
+ $sql = "{$sql} WHERE $params";
+ }
+
+ parent::setQuery($sql);
+ }
+
+ // }}}
+
+ // {{{ toHtml()
+
+ public function toHtml()
+ {
+ $GLOBALS['styleSheets'][] = MEDIA_BASE_URL . 'Toolkit/Coupons/styles.css';
+ return parent::toHTML();
+ }
+
+ // }}}
+}
--- /dev/null
+CREATE SCHEMA coupons;
+GRANT ALL ON SCHEMA coupons TO nobody;
+
+--
+-- Tables
+--
+\i ./tables/coupon_category.sql
+\i ./tables/coupons.sql
+\i ./tables/coupon_categories2toolbox_pages.sql
+\i ./tables/coupon_categories2toolbox_pages_draft.sql
+
+--
+-- Procedures
+--
+
+--
+-- Modules
+--
--- /dev/null
+CREATE SCHEMA coupons;
+GRANT ALL ON SCHEMA coupons TO nobody;
+
+--
+-- Tables
+--
+\i ./tables/coupon_category.sql
+\i ./tables/coupons_with_members.sql
+\i ./tables/coupon_categories2toolbox_pages.sql
+\i ./tables/coupon_categories2toolbox_pages_draft.sql
+
+--
+-- Procedures
+--
+
+--
+-- Modules
+--
--- /dev/null
+--
+-- This will drop everything in the toolbox schema.
+-- Nothing better be in here except toolbox related objects
+-- or it will be dropped
+--
+-- The force is strong w/ this one, use it wisely.
+--
+DROP SCHEMA IF EXISTS coupons CASCADE;
+
+DROP TABLE IF EXISTS toolbox.coupon_categories2toolbox_pages;
+DROP TABLE IF EXISTS toolbox.coupon_categories2toolbox_pages_draft;
--- /dev/null
+DROP TABLE IF EXISTS toolbox.coupon_categories2toolbox_pages CASCADE;
+
+CREATE TABLE toolbox.coupon_categories2toolbox_pages
+(page INTEGER NOT NULL
+ REFERENCES toolbox.pages (id)
+ ON UPDATE CASCADE
+ ON DELETE CASCADE,
+ category INTEGER NOT NULL
+ REFERENCES coupons.coupon_category (id)
+ ON UPDATE CASCADE
+ ON DELETE CASCADE);
+
+GRANT ALL ON toolbox.coupon_categories2toolbox_pages TO nobody;
--- /dev/null
+DROP TABLE IF EXISTS toolbox.coupon_categories2toolbox_pages_draft CASCADE;
+
+CREATE TABLE toolbox.coupon_categories2toolbox_pages_draft
+(page INTEGER NOT NULL
+ REFERENCES toolbox.pages_draft (id)
+ ON UPDATE CASCADE
+ ON DELETE CASCADE,
+ category INTEGER NOT NULL
+ REFERENCES coupons.coupon_category (id)
+ ON UPDATE CASCADE
+ ON DELETE CASCADE);
+
+GRANT ALL ON toolbox.coupon_categories2toolbox_pages_draft TO nobody;
--- /dev/null
+DROP TABLE IF EXISTS coupons.coupon_category CASCADE;
+
+CREATE TABLE coupons.coupon_category
+(id SERIAL,
+ name TEXT UNIQUE NOT NULL,
+ PRIMARY KEY (id));
+
+DELETE FROM coupons.coupon_category;
+ALTER SEQUENCE coupons.coupon_category_id_seq RESTART WITH 1;
+INSERT INTO coupons.coupon_category (name) VALUES ('Accommodations');
+INSERT INTO coupons.coupon_category (name) VALUES ('Dining');
+INSERT INTO coupons.coupon_category (name) VALUES ('Entertainment');
+INSERT INTO coupons.coupon_category (name) VALUES ('Home Improvement');
+
+GRANT ALL ON coupons.coupon_category_id_seq TO nobody;
+GRANT ALL ON coupons.coupon_category TO nobody;
--- /dev/null
+DROP TABLE IF EXISTS coupons.coupons CASCADE;
+
+CREATE TABLE coupons.coupons
+(id SERIAL NOT NULL,
+ title TEXT,
+ description TEXT,
+ url TEXT,
+ sdate DATE NOT NULL,
+ edate DATE NOT NULL,
+ expiration DATE NOT NULL,
+ category TEXT
+ REFERENCES coupons.coupon_category (name)
+ ON UPDATE CASCADE
+ ON DELETE SET NULL,
+ active BOOLEAN NOT NULL DEFAULT FALSE,
+ pending BOOLEAN DEFAULT FALSE,
+ image TEXT,
+ CHECK (sdate <= edate),
+ CHECK (sdate <= expiration),
+ CHECK (edate <= expiration),
+ PRIMARY KEY (id));
+
+GRANT ALL ON coupons.coupons_id_seq TO nobody;
+GRANT ALL ON coupons.coupons TO nobody;
--- /dev/null
+DROP TABLE IF EXISTS coupons.coupons CASCADE;
+
+CREATE TABLE coupons.coupons
+(id SERIAL NOT NULL,
+ title TEXT,
+ description TEXT,
+ url TEXT,
+ sdate DATE NOT NULL,
+ edate DATE NOT NULL,
+ expiration DATE NOT NULL,
+ category TEXT
+ REFERENCES coupons.coupon_category (name)
+ ON UPDATE CASCADE
+ ON DELETE SET NULL,
+ active BOOLEAN NOT NULL DEFAULT FALSE,
+ member INTEGER
+ REFERENCES members.member (member_id)
+ ON UPDATE CASCADE
+ ON DELETE CASCADE,
+ pending BOOLEAN DEFAULT FALSE,
+ image TEXT,
+ CHECK (sdate <= edate),
+ CHECK (sdate <= expiration),
+ CHECK (edate <= expiration),
+ PRIMARY KEY (id));
+
+GRANT ALL ON coupons.coupons_id_seq TO nobody;
+GRANT ALL ON coupons.coupons TO nobody;
--- /dev/null
+<?php
+
+/**
+ * Base class for decorators
+ *
+ * PHP version 5
+ *
+ * @category Coupons
+ * @package Toolkit_Coupons
+ * @author Jamie Kahgee <jamie@gaslightmedia.com>
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version CVS: $Id: Decorator.php,v 1.1 2010/02/12 21:16:33 jamie Exp $
+ * @link <>
+ */
+
+
+/**
+ * Base class for decorators
+ *
+ * @category Coupons
+ * @package Toolkit_Coupons
+ * @author Jamie Kahgee <jamie@gaslightmedia.com>
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @link <>
+ */
+abstract class Toolkit_Coupons_Decorator
+{
+ // {{{ properties
+
+
+ /**
+ * Banner object that will be decorated
+ * @var Toolkit_Coupons_Coupon
+ * @access protected
+ */
+ protected $coupon;
+
+ // }}}
+ // {{{ __construct()
+
+
+ /**
+ * constructor
+ *
+ * create a shallow copy of the coupon passed in so we can manipulate
+ * it all we want and not worry about affecting the original coupon
+ *
+ * @param Toolkit_Coupons_Coupon $coupon Coupon to be decorated
+ *
+ * @return void
+ * @access protected
+ */
+ protected function __construct(Toolkit_Coupons_Coupon $coupon)
+ {
+ // Clone the coupon object so we keep original properties the same
+ $copiedCoupon = clone $coupon;
+
+ $this->coupon = $copiedCoupon;
+ }
+
+ // }}}
+ // {{{ getCoupon()
+
+
+ /**
+ * Get the coupon we are decorating
+ *
+ * @return Toolkit_Coupons_Coupon coupon object
+ * @access public
+ */
+ public function getCoupon()
+ {
+ return $this->coupon;
+ }
+
+ // }}}
+}
+?>
--- /dev/null
+<?php
+class Toolkit_Coupons_Exception extends Exception {}
+?>
--- /dev/null
+<?php
+interface Toolkit_Coupons_ICoupon
+{
+ public static function &create(array $data);
+ public static function &fetch(PDO $dbh, $id);
+ public function save(PDO $dbh);
+ public function update(PDO $dbh, array $data);
+}
--- /dev/null
+<?php
+interface Toolkit_Coupons_ICouponFactory
+{
+ public function createCoupon(array $c);
+ public function &fetch(PDO $dbh, $id);
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Interface definition for coupon decorators
+ *
+ * PHP version 5
+ *
+ * @category Coupons
+ * @package Toolkit_Coupons
+ * @author Jamie Kahgee <jamie@gaslightmedia.com>
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version CVS: $Id: IDecorator.php,v 1.1 2010/02/12 21:16:33 jamie Exp $
+ * @link <>
+ */
+
+/**
+ * Interface definition for coupon decorators
+ *
+ * @category Coupons
+ * @package Toolkit_Coupons
+ * @author Jamie Kahgee <jamie@gaslightmedia.com>
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @link <>
+ */
+interface Toolkit_Coupons_IDecorator
+{
+ /**
+ * create HTML to be displayed on web page
+ *
+ * @return string HTML output
+ * @access public
+ */
+ public function toHtml();
+
+ public static function create(Toolkit_Coupons_Coupon $c);
+}
+?>
--- /dev/null
+<?php
+interface Toolkit_Coupons_IDecoratorFactory
+{
+ public function createDecorator(Toolkit_Coupons_Coupon $c);
+}
+?>
--- /dev/null
+<?php
+interface Toolkit_Coupons_IHtmlElement
+{
+ /**
+ * @return string html code
+ */
+ public function __toString();
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Coupon Image Element
+ *
+ * PHP version 5
+ *
+ * @category Toolkit_Coupons
+ * @package Coupons
+ * @author Jamie Kahgee <jamie@gaslightmedia.com>
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version CVS: $Id: Image.php,v 1.1 2010/02/12 21:16:33 jamie Exp $
+ * @link <>
+ * @see References to other sections (if any)...
+ */
+
+/**
+ * Coupon Image Element
+ *
+ * @category Toolkit_Coupons
+ * @package Coupons
+ * @author Jamie Kahgee <jamie@gaslightmedia.com>
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version Release: @package_version@
+ * @link <>
+ * @see References to other sections (if any)...
+ */
+abstract class Toolkit_Coupons_Image
+{
+ // {{{ properties
+
+ /**
+ * Elements src attribute
+ * @var string
+ * @access protected
+ */
+ protected $src;
+
+ /**
+ * Elements alt attribute
+ * @var string
+ * @access protected
+ */
+ protected $alt;
+
+ // }}}
+
+ // {{{ getAlt()
+
+ /**
+ * Get the alt attribute
+ *
+ * @return string alt attribue value
+ * @access public
+ */
+ public function getAlt()
+ {
+ return $this->alt;
+ }
+
+ // }}}
+ // {{{ getSrc()
+
+ /**
+ * Get the src attribute
+ *
+ * @return string src attribute value
+ * @access public
+ */
+ public function getSrc()
+ {
+ return $this->src;
+ }
+
+ // }}}
+}
+?>
--- /dev/null
+<?php
+class Toolkit_Coupons_ImageFactory
+{
+ public static function getImage(array $data)
+ {
+ if (isset($data['image']) && !empty($data['image'])) {
+ return new Toolkit_Coupons_RealImage($data['image']);
+ } else {
+ return new Toolkit_Coupons_NullImage();
+ }
+ }
+}
+?>
--- /dev/null
+<?php
+class Toolkit_Coupons_MemberCoupon extends Toolkit_Coupons_WebCoupon
+ implements Toolkit_Coupons_ICoupon, Toolkit_Coupons_IHtmlElement
+{
+ // {{{ properties
+ protected $member;
+ protected $pending;
+
+ // }}}
+ // {{{ __construct()
+ public function __construct(array $data)
+ {
+ parent::__construct($data);
+
+ if (isset($data['member']) && !empty($data['member'])) {
+ if (!ctype_digit((string)$data['member'])) {
+ throw new InvalidArgumentException(
+ 'member must be an integer'
+ );
+ }
+
+ settype($data['member'], 'int');
+ $this->member = $data['member'];
+ }
+
+ $this->pending = $data['pending'];
+ }
+
+ // }}}
+ // {{{ __toString()
+ // @codeCoverageIgnoreStart
+
+ /**
+ * Convert the coupon object to a HTML string
+ *
+ * @return string HTML output of the coupon
+ * @access public
+ */
+ public function __toString()
+ {
+ $imgUrl = $this->getImage()->getSrc();
+ $imgTpl = '<img alt="%s" src="%s%s">';
+ $img = '';
+ if (!empty($imgUrl)) {
+ $img = sprintf($imgTpl, 'coupon thumbnail', COUPON_THUMB, $imgUrl);
+ }
+
+ $aUrl = $this->getUrl();
+ $aTpl = '<a class="coupon-url" href="%s" target="_blank">Web Site</a>';
+ $anchor = '';
+ if (!empty($aUrl)) {
+ $anchor = sprintf($aTpl, $aUrl);
+ }
+
+ $desc = $this->getDescription();
+ $description = '';
+ if (!empty($desc)) {
+ $description = "<p>$desc</p>";
+ }
+
+ $chkBoxTpl = '<input type="checkbox" name="coupon_%d" value="T">';
+ $chkBox = sprintf($chkBoxTpl, $this->getId());
+
+ $out = '<div class="couponitem">';
+ $out .= '<div class="oldBackground">';
+ $out .= '<label class="changeParent">';
+ $out .= $chkBox;
+ $out .= 'Select this coupon';
+ $out .= '</label>';
+ $out .= '</div>';
+ $out .= '<strong>';
+ $out .= $this->getMember();
+ $out .= '</strong>';
+ $out .= '<strong>';
+ $out .= $this->getTitle();
+ $out .= '</strong>';
+ $out .= $img;
+ $out .= $description;
+ $out .= $anchor;
+ $out .= '<div class="expire_date">';
+ $out .= 'Expires: ';
+ $out .= $this->getExpiration()->format('%m/%d/%Y');
+ $out .= '</div>';
+ $out .= '</div>';
+
+ return $out;
+ }
+
+ // @codeCoverageIgnoreEnd
+ // }}}
+
+ // {{{ &create()
+ public static function &create(array $data)
+ {
+ return new self($data);
+ }
+
+ // }}}
+
+ // {{{ &fetch()
+
+ /**
+ * Fetch an instance of a coupon by db id
+ *
+ * @param PDO $dbh Database handler
+ * @param integer $id ID of coupon to fetch
+ *
+ * @returns Toolkit_Coupons_MemberCoupon concrete coupon
+ * @throws Toolkit_Coupons_Exception on invalid argument or pdo exception
+ * @access public
+ * @static
+ */
+ public static function &fetch(PDO $dbh, $id)
+ {
+ try {
+ if (!ctype_digit((string)$id)) {
+ throw new InvalidArgumentException(
+ "\$id must be an integer [$id] given"
+ );
+ }
+ $sql = "
+ SELECT *
+ FROM coupons
+ WHERE id = :id";
+
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(':id', $id, PDO::PARAM_INT);
+ $stmt->execute();
+
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ $row['image'] = Toolkit_Coupons_ImageFactory::getImage($row);
+ $row['sdate']
+ = new Date(strtotime($row['sdate']), DATE_FORMAT_UNIXTIME);
+ $row['edate']
+ = new Date(strtotime($row['edate']), DATE_FORMAT_UNIXTIME);
+ $row['expiration']
+ = new Date(strtotime($row['expiration']), DATE_FORMAT_UNIXTIME);
+
+ return new self($row);
+ } catch (InvalidArgumentException $e) {
+ Toolkit_Logger::logException('Invalid Arg', $e);
+ throw new Toolkit_Coupons_Exception('error fetching coupon');
+ } catch (PDOException $e) {
+ Toolkit_Logger::logException('DB Error', $e);
+ throw new Toolkit_Coupons_Exception('error fetching coupon');
+ }
+ }
+
+ // }}}
+
+ // {{{ getMember()
+ public function getMember()
+ {
+ return $this->member;
+ }
+
+ // }}}
+ // {{{ getPending()
+ public function getPending()
+ {
+ return $this->pending;
+ }
+
+ // }}}
+
+ // {{{ setMember()
+ public function setMember($member)
+ {
+ if ((string)$member && !ctype_digit((string)$member)) {
+ throw new InvalidArgumentException('member must be an integer');
+ }
+ if ($member == '') {
+ $this->member = null;
+ } else {
+ settype($member, 'int');
+ $this->member = $member;
+ }
+ }
+
+ // }}}
+ // {{{ setPending()
+ public function setPending($pending)
+ {
+ settype($member, 'bool');
+ $this->pending = $pending;
+ }
+
+ // }}}
+
+ // {{{ update()
+ public function update(PDO $dbh, array $data)
+ {
+ if (isset($data['member'])) {
+ $this->setMember($data['member']);
+ }
+ if ($data['active'] && $data['pending']) {
+ $this->setPending(false);
+ }
+
+ return parent::update($dbh, $data);
+ }
+
+ // }}}
+}
--- /dev/null
+<?php
+class Toolkit_Coupons_MemberCouponFactory extends Toolkit_Coupons_CouponFactory
+ implements Toolkit_Coupons_ICouponFactory
+{
+ public function createCoupon(array $c)
+ {
+ return Toolkit_Coupons_MemberCoupon::create($c);
+ }
+
+ public function &fetch(PDO $dbh, $id)
+ {
+ return Toolkit_Coupons_MemberCoupon::fetch($dbh, $id);
+ }
+}
--- /dev/null
+<?php
+
+class Toolkit_Coupons_Navigation extends Toolkit_NavigationAbstract
+ implements Toolkit_INavigation
+{
+ // {{{ __construct()
+
+ public function __construct(
+ HTML_Menu $menu,
+ HTML_Menu_Renderer $rEngine
+ ) {
+ $this->menu = $menu;
+ $this->rEngine = $rEngine;
+ $this->currIndex = 'listCoupons';
+ }
+
+ // }}}
+ // {{{ setNavTemplates()
+
+ protected function setNavTemplates()
+ {
+ $tpl = '<li><a href="%s" title="%s">{Title}</a></li>';
+ $this->rEngine->setEntryTemplate(
+ HTML_MENU_ENTRY_INACTIVE,
+ sprintf($tpl, '{url}', '{desc}', '{Title}')
+ );
+ $this->rEngine->setEntryTemplate(
+ HTML_MENU_ENTRY_ACTIVE,
+ sprintf($tpl, '{url}', '{desc}', '{Title}')
+ );
+ $this->rEngine->setEntryTemplate(
+ HTML_MENU_ENTRY_ACTIVEPATH,
+ sprintf($tpl, '{url}', '{desc}', '{Title}')
+ );
+ $this->rEngine->setMenuTemplate('', '');
+ $this->rEngine->setRowTemplate('<ul class="admin_nav">', '</ul>');
+ }
+
+ // }}}
+ // {{{ setCurrentIndex()
+
+ protected function setCurrentIndex()
+ {
+ $this->menu->forceCurrentIndex($_GET['page']);
+ }
+
+ // }}}
+ // {{{ getNavSructure()
+ // @codeCoverageIgnoreStart
+
+ /**
+ * Sets up a multi dimensional array used for the nav structure
+ *
+ * @param Config_Container $c Application configuration
+ *
+ * @return array navigational array hash
+ * @access public
+ */
+ public function getNavStructure(Config_Container $c)
+ {
+ // get reference to [listing type] section of config file
+ $singularType = $c->getItem('section', 'listing type')
+ ->getItem('directive', 'singular')
+ ->getContent();
+ $pluralType = $c->getItem('section', 'listing type')
+ ->getItem('directive', 'plural')
+ ->getContent();
+
+ $nav = array(
+ 'listCoupons' => array(
+ 'Title' => "List {$pluralType}",
+ 'url' => MEDIA_BASE_URL . 'admin/coupons.php?page=listCoupons&module=listCoupons',
+ 'desc' => "Display all the {$pluralType}",
+ ),
+ 'editCoupon' => array(
+ 'Title' => "Add {$singularType}",
+ 'url' => MEDIA_BASE_URL . 'admin/coupons.php?page=editCoupon&module=editCoupon',
+ 'desc' => "Edit a {$singularType}"
+ ),
+ 'categories' => array(
+ 'Title' => 'Categories',
+ 'url' => MEDIA_BASE_URL . 'admin/coupons.php?page=categories&module=listCategories',
+ 'desc' => "Display all the Categories",
+ ),
+ 'editCategory' => array(
+ 'Title' => 'Add Category',
+ 'url' => MEDIA_BASE_URL . 'admin/coupons.php?page=editCategory&module=editCategory',
+ 'desc' => 'Edit a Category',
+ ),
+ );
+
+ return $nav;
+ }
+
+ // @codeCoverageIgnoreEnd
+ // }}}
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Coupon Image Element
+ *
+ * PHP version 5
+ *
+ * @category Toolkit_Coupons
+ * @package Coupons
+ * @author Jamie Kahgee <jamie@gaslightmedia.com>
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version CVS: $Id: NullImage.php,v 1.1 2010/02/12 21:16:33 jamie Exp $
+ * @link <>
+ * @see References to other sections (if any)...
+ */
+
+/**
+ * Coupon Image Element
+ *
+ * @category Toolkit_Coupons
+ * @package Coupons
+ * @author Jamie Kahgee <jamie@gaslightmedia.com>
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version Release: @package_version@
+ * @link <>
+ * @see References to other sections (if any)...
+ */
+class Toolkit_Coupons_NullImage extends Toolkit_Coupons_Image
+ implements Toolkit_Coupons_IHtmlElement
+{
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * Sets elements attributes
+ *
+ * @return void
+ * @access public
+ */
+ public function __construct()
+ {
+ $this->src = $this->alt = null;
+ }
+
+ // }}}
+ // {{{ __toString()
+
+ /**
+ * Magic print function
+ *
+ * retrieves a null html element
+ *
+ * @return string Html image element
+ * @access public
+ */
+ public function __toString()
+ {
+ return '';
+ }
+
+ // }}}
+}
+?>
--- /dev/null
+<?php
+
+class Toolkit_Coupons_PageWidget
+{
+ // {{{ properties
+ private $_cFactory;
+ private $_coupons;
+ private $_searchForm = null;
+
+ // }}}
+ // {{{ __construct()
+
+ public function __construct(
+ Toolkit_Coupons_CouponFactory $cFactory,
+ Toolkit_Coupons_Coupons $coupons
+ ) {
+ $this->_cFactory = $cFactory;
+ $this->_coupons = $coupons;
+ }
+
+ // }}}
+
+ // {{{ addAllCategories()
+
+ public function addAllCategories(PDO $dbh)
+ {
+ try {
+ $sql = "
+ SELECT id
+ FROM coupons";
+
+ $params = array(
+ 'CURRENT_DATE BETWEEN sdate AND edate',
+ 'active = true',
+ );
+
+ if ( defined('MEMBERS_DB')
+ && MEMBERS_DB
+ && isset($_GET['member_id'])
+ && ctype_digit($_GET['member_id'])
+ ) {
+ $params[] = 'member = ' . $dbh->quote($_GET['member_id']);
+ }
+
+ $params = implode(' AND ', $params);
+ $sql = "$sql WHERE $params";
+
+ foreach ($dbh->query($sql) as $row) {
+ if ($coupon = $this->_cFactory->fetch($dbh, $row['id'])) {
+ $this->_coupons->addCoupon($coupon);
+ }
+ }
+ } catch (PDOException $e) {
+ Toolkit_Logger::logException("DB Error", $e);
+ throw new Toolkit_Coupons_Exception('Error adding all coupons');
+ }
+ }
+
+ // }}}
+ // {{{ addPageCategories()
+
+ public function addPageCategories(PDO $dbh, $catid)
+ {
+ try {
+ if (!ctype_digit((string)$catid)) {
+ throw new InvalidArgumentException('$catid must be an integer');
+ }
+
+ // Determine if coupon category filter has any entries
+ $sql = "
+ SELECT *
+ FROM coupon_categories2toolbox_pages
+ WHERE page = :catid";
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(
+ ':catid',
+ $catid,
+ PDO::PARAM_INT
+ );
+ $stmt->execute();
+ $ccats = ($stmt->rowCount() > 0);
+
+ // If using coupon category filters
+ if ($ccats) {
+ $sql = "
+ SELECT c.id
+ FROM coupons c
+ JOIN coupon_category cc
+ ON c.category = cc.name
+ JOIN coupon_categories2toolbox_pages cc2tp
+ ON cc.id = cc2tp.category";
+
+ $params = array(
+ 'c.active = true',
+ "cc2tp.page = :catid"
+ );
+ } else {
+ // Not using coupon category filters
+ $sql = "
+ SELECT c.id
+ FROM coupons c
+ JOIN coupon_category cc
+ ON c.category = cc.name";
+
+ $params = array(
+ 'c.active = true'
+ );
+ }
+
+
+ if ( isset($_GET['submit'])
+ && isset($_GET['coupon_category'])
+ && ctype_digit($_GET['coupon_category'])
+ ) {
+ $params[] = 'cc.id = ' . $dbh->quote($_GET['coupon_category']);
+ }
+
+ if ( defined('MEMBERS_DB')
+ && MEMBERS_DB
+ && isset($_GET['member_id'])
+ && ctype_digit($_GET['member_id'])
+ ) {
+ $params[] = 'c.member = ' . $dbh->quote($_GET['member_id']);
+ }
+ if (!empty($_GET['months']) && preg_match('/([0-9]{2}) ([0-9]{4})/', $_GET['months'], $found)) {
+ try {
+ $date = new DateTime($found[2] . '-' . $found[1] . '-01');
+ $params[] = "(DATE '{$date->format('Y-m-d')}', DATE '{$date->format('Y-m-t')}') OVERLAPS (c.sdate, c.edate)";
+ } catch(Exception $e) {
+ Toolkit_Common::handleError($e);
+ }
+ } else {
+ $params[] = 'CURRENT_DATE BETWEEN c.sdate AND c.edate';
+ }
+
+ $params = implode(' AND ', $params);
+ $sql = "$sql WHERE $params";
+
+ $stmt = $dbh->prepare($sql);
+ if ($ccats) {
+ $stmt->bindParam(':catid', $catid, PDO::PARAM_INT);
+ }
+ $stmt->execute();
+
+ while ($row = $stmt->fetch()) {
+ if ($coupon = $this->_cFactory->fetch($dbh, $row['id'])) {
+ $this->_coupons->addCoupon($coupon);
+ }
+ }
+ } catch (InvalidArgumentException $e) {
+ Toolkit_Logger::logException("Invalid Arg", $e);
+ throw new Toolkit_Coupons_Exception('Invalid page id');
+ } catch (PDOException $e) {
+ Toolkit_Logger::logException("DB Error", $e);
+ throw new Toolkit_Coupons_Exception('Error adding page coupons');
+ }
+ }
+
+ // }}}
+
+ // {{{ _getHead()
+
+ private function _getHead(HTML_Template_Flexy $tEngine, $template)
+ {
+ $page = new stdClass();
+ $tEngine->compile($template);
+ return $tEngine->bufferedOutputObject($page);
+ }
+
+ // }}}
+
+ // {{{ setSearchForm()
+
+ public function setSearchForm(HTML_QuickForm $form)
+ {
+ $this->_searchForm = $form;
+ }
+
+ // }}}
+
+ // {{{ toHtml()
+ // @codeCoverageIgnoreStart
+
+ public function toHtml(
+ HTML_QuickForm $form,
+ HTML_Template_Flexy $tEngine,
+ $template
+ ) {
+ $GLOBALS['styleSheets'][]
+ = MEDIA_BASE_URL . 'Toolkit/Coupons/css/coupons.css';
+ $GLOBALS['bottomScripts'][]
+ = MEDIA_BASE_URL . 'Toolkit/Coupons/libjs/coupons.js';
+
+ $print['all'] =& HTML_QuickForm::createElement(
+ 'submit',
+ 'printAll',
+ 'Print all coupons'
+ );
+ $print['sel'] =& HTML_QuickForm::createElement(
+ 'submit',
+ 'printSel',
+ 'Print selected only'
+ );
+ $form->addGroup($print, 'print', '', '', false);
+ $form->addElement('static', null, null, $this->_coupons);
+ $form->addElement('hidden', 'coupons_catid', $_GET['coupon_category']);
+ $form->addElement('hidden', 'months', $_GET['months']);
+ $form->addElement('hidden', 'catid', $_GET['catid']);
+ $renderer =& $form->defaultRenderer();
+ $renderer->clearAllTemplates();
+ $renderer->setGroupTemplate(
+ "<div class=\"coupon-buttons\">\n{content}\n</div>",
+ 'print'
+ );
+
+ $page = new stdClass();
+ $page->coupons = $form->toHtml();
+ if (!is_null($this->_searchForm)) {
+ $page->searchForm = $this->_searchForm->toHtml();
+ }
+
+ $tEngine->compile($template);
+ $html .= $tEngine->bufferedOutputObject($page);
+
+ return $html;
+ }
+
+ // @codeCoverageIgnoreEnd
+ // }}}
+}
--- /dev/null
+<?php
+
+/**
+ * Coupon Image Element
+ *
+ * PHP version 5
+ *
+ * @category Toolkit_Coupons
+ * @package Coupons
+ * @author Jamie Kahgee <jamie@gaslightmedia.com>
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version CVS: $Id: RealImage.php,v 1.1 2010/02/12 21:16:33 jamie Exp $
+ * @link <>
+ * @see References to other sections (if any)...
+ */
+
+/**
+ * Coupon Image Element
+ *
+ * @category Toolkit_Coupons
+ * @package Coupons
+ * @author Jamie Kahgee <jamie@gaslightmedia.com>
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version Release: @package_version@
+ * @link <>
+ * @see References to other sections (if any)...
+ */
+class Toolkit_Coupons_RealImage extends Toolkit_Coupons_Image
+ implements Toolkit_Coupons_IHtmlElement
+{
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * Sets elements attributes
+ *
+ * @param string $src src attribute value
+ * @param string $alt alt attribute value (optional)
+ *
+ * @return void
+ * @access public
+ */
+ public function __construct($src, $alt = null)
+ {
+ if (empty($src)) {
+ throw new InvalidArgumentException('$src cannot be empty');
+ }
+
+ $this->src = $src;
+ $this->alt = $alt;
+ }
+
+ // }}}
+ // {{{ __toString()
+
+ /**
+ * Magic print function
+ *
+ * retrieves a generic html img element
+ *
+ * @return string Html image element
+ * @access public
+ */
+ public function __toString()
+ {
+ $format = '<img src="%s" alt="%s">';
+ return sprintf($format, $this->src, $this->alt);
+ }
+
+ // }}}
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Decorator for coupon thumbnail images
+ *
+ * PHP version 5
+ *
+ * @category Coupons
+ * @package Toolkit_Coupons
+ * @author Jamie Kahgee <jamie@gaslightmedia.com>
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version CVS: $Id: ThumbnailDecorator.php,v 1.1 2010/02/12 21:16:33 jamie Exp $
+ * @link <>
+ */
+
+
+/**
+ * Decorator for coupon thumbnail images
+ *
+ * @category Coupons
+ * @package Toolkit_Coupons
+ * @author Jamie Kahgee <jamie@gaslightmedia.com>
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @link <>
+ */
+class Toolkit_Coupons_ThumbnailDecorator extends Toolkit_Coupons_Decorator
+ implements Toolkit_Coupons_IDecorator
+{
+ // {{{ create()
+
+ /**
+ * Create a new thumbnail coupon decorator
+ *
+ * @param Toolkit_Coupons_Coupon $c coupon to decorate
+ *
+ * @return Toolkit_Coupons_ThumbnailDecorator decorator object
+ * @access public
+ * @static
+ */
+ public static function create(Toolkit_Coupons_Coupon $c)
+ {
+ return new self($c);
+ }
+
+ // }}}
+ // {{{ toHtml()
+
+
+ /**
+ * Convert the coupon to a HTML string
+ *
+ * @return string HTML output of the coupon
+ * @access public
+ */
+ public function toHtml()
+ {
+ $imgUrl = COUPON_THUMB . $this->coupon->getImage()->getSrc();
+
+ $imgTpl = '<img alt="%s" src="%s">';
+
+ return sprintf(
+ $imgTpl,
+ 'coupon thumbnail',
+ COUPON_THUMB . $this->coupon->getImage()->getSrc()
+ );
+ }
+
+ // }}}
+}
--- /dev/null
+<?php
+class Toolkit_Coupons_ThumbnailFactory
+ implements Toolkit_Coupons_IDecoratorFactory
+{
+ public function createDecorator(Toolkit_Coupons_Coupon $c)
+ {
+ return Toolkit_Coupons_ThumbnailDecorator::create($c);
+ }
+}
--- /dev/null
+<?php
+// vim:set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker syntax=php:
+
+/**
+ * Coupons search form
+ *
+ * PHP version 5
+ *
+ * @category Coupons
+ * @package Toolkit_Coupons
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: UserSearch.php,v 1.5 2010/08/12 18:07:21 matrix Exp $
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Coupons search form
+ *
+ * @category Coupons
+ * @package Toolkit_Coupons
+ * @author Jamie Kahgee <jamie@gaslightmedia.com>
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @link <>
+ */
+class Toolkit_Coupons_UserSearch extends Toolkit_FormBuilder
+{
+ // {{{ properties
+
+ /**
+ * 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.
+ *
+ * @var string
+ * @access protected
+ */
+ protected $registeredRules = array();
+
+ // }}}
+
+ // {{{ configureConstants()
+
+ /**
+ * Configure constant form values
+ *
+ * @param integer $catid Page catid
+ *
+ * @return void
+ * @access public
+ */
+ public function configureConstants($catid)
+ {
+ if (!ctype_digit((string)$catid)) {
+ throw new InvalidArgumentException('$catid must be an integer');
+ }
+
+ $c = array(
+ 'catid' => $catid,
+ );
+
+ $this->setupConstants($c);
+ }
+
+ // }}}
+ // {{{ configureElements()
+
+ /**
+ * Configure the elements that should be on the form
+ *
+ * @param PDO $dbh Database handler
+ * @param integer $catid Page catid
+ *
+ * @return void
+ * @access public
+ */
+ public function configureElements(PDO $dbh, $catid)
+ {
+ if (!ctype_digit((string)$catid)) {
+ throw new InvalidArgumentException('$catid must be an integer');
+ }
+
+ $e = array();
+
+ $categories = $this->_getCategories($dbh, $catid);
+ $months = $this->_getMonths($dbh, $catid);
+ // All Grouped Elements are created here.
+
+ // All Elements are created here. This includes group element definitions.
+ $e[] = array(
+ 'type' => 'hidden',
+ 'req' => false,
+ 'name' => 'catid',
+ );
+ $e[] = array(
+ 'type' => 'select',
+ 'req' => false,
+ 'name' => 'months',
+ 'opts' => array(
+ '' => '-- All Months --'
+ ) + $months
+ );
+ $e[] = array(
+ 'type' => 'select',
+ 'req' => false,
+ 'name' => 'coupon_category',
+ 'opts' => array(
+ '' => '-- All Categories --'
+ ) + $categories
+ );
+ $e[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'submit',
+ 'display' => 'Search'
+ );
+
+ $this->setupElements($e);
+ }
+
+ // }}}
+ // {{{ configureFilters()
+
+ /**
+ * Sets up filters for form elements
+ *
+ * These filters will be run before the rules are checked
+ * against the elements
+ *
+ * @return void
+ * @access public
+ */
+ public function configureFilters()
+ {
+ $f = array();
+ $f[] = array(
+ 'element' => '__ALL__',
+ 'filter' => 'trim'
+ );
+
+ $this->setupFilters($f);
+ }
+
+ // }}}
+ // {{{ configureForm()
+
+ /**
+ * Configures the entire form so it can be rendered
+ *
+ * @param PDO $dbh Database handler
+ * @param integer $catid Page catid
+ *
+ * @return void
+ * @access public
+ */
+ public function configureForm(PDO $dbh, $catid)
+ {
+ if (!ctype_digit((string)$catid)) {
+ throw new InvalidArgumentException('$catid must be an integer');
+ }
+
+ $this->configureElements($dbh, $catid);
+ $this->configureFilters();
+ $this->configureRules();
+ $this->configureConstants($catid);
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Defines rules for the forms elements
+ *
+ * @return void
+ * @access public
+ */
+ public function configureRules()
+ {
+ $r = array();
+ $this->setupRules($r);
+ }
+
+ // }}}
+
+ private function _getMonths(PDO $dbh, $catid)
+ {
+ try {
+ $currentDate = new DateTime();
+ } catch(Exception $e) {
+ Toolkit_Common::handleError($e);
+ }
+ try {
+ // Determine if coupon category filter has any entries
+ $sql = "
+ SELECT *
+ FROM coupon_categories2toolbox_pages
+ WHERE page = :catid";
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(':catid', $catid, PDO::PARAM_INT);
+ $stmt->execute();
+ $ccats = ($stmt->rowCount() > 0);
+
+ // If using coupon category filters
+ if ($ccats) {
+ $sql = "
+ SELECT c.sdate,c.edate,age(c.edate, current_date) as duration
+ FROM coupons c
+ JOIN coupon_category cc
+ ON c.category = cc.name
+ JOIN coupon_categories2toolbox_pages cc2tp
+ ON cc.id = cc2tp.category
+ WHERE cc2tp.page = :catid
+ AND c.edate >= current_date
+ ORDER BY c.sdate,c.edate";
+ } else {
+ $sql = "
+ SELECT c.sdate,c.edate,age(c.edate, current_date) as duration
+ FROM coupons c
+ JOIN coupon_category cc
+ ON c.category = cc.name
+ WHERE c.edate >= current_date
+ ORDER BY c.sdate,c.edate";
+ }
+
+ $months = array();
+ $stmt = $dbh->prepare($sql);
+ if ($ccats) {
+ $stmt->bindParam(':catid', $catid, PDO::PARAM_INT);
+ }
+ $stmt->execute();
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ try {
+ $date = new DateTime($row['sdate']);
+ if (preg_match('/([0-9]*) years?|([0-9]*) mons?|([0-9]*) days?/', $row['duration'], $found)) {
+ if ($date > $currentDate) {
+ $months[$date->format('m Y')] = $date->format('M Y');
+ } else {
+ $months[$currentDate->format('m Y')] = $currentDate->format('M Y');
+ }
+ if ($found[1]) {
+ for ($i = 1; $i <= $found[1]; ++$i) {
+ for ($m = 1; $m <= 12; ++$m) {
+ $date->modify('+1 month');
+ if ($date > $currentDate) {
+ $months[$date->format('m Y')] = $date->format('M Y');
+ }
+ }
+ }
+ }
+ if ($found[2]) {
+ for ($m = 1; $m <= $found[2]; ++$m) {
+ $date->modify('+1 month');
+ if ($date > $currentDate) {
+ $months[$date->format('m Y')] = $date->format('M Y');
+ }
+ }
+ }
+ if ($found[3]) {
+ for ($d = 1; $d <= $found[3]; ++$d) {
+ $date->modify('+1 day');
+ if ($date > $currentDate) {
+ $months[$date->format('m Y')] = $date->format('M Y');
+ }
+ }
+ }
+ }
+ } catch(Exception $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+ return $months;
+ } catch (PDOException $e) {
+ Toolkit_Logger::logException('DB Error', $e);
+ throw new Toolkit_Coupons_Exception('Error retrieving months');
+ }
+ }
+
+ // {{{ _getCategories()
+
+ /**
+ * Get the coupon categories available
+ *
+ * @param PDO $dbh Database handler
+ *
+ * @return array coupon categories
+ * @access private
+ */
+ private function _getCategories(PDO $dbh, $catid)
+ {
+ try {
+ // Determine if coupon category filter has any entries
+ $sql = "
+ SELECT *
+ FROM coupon_categories2toolbox_pages
+ WHERE page = :catid";
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(':catid', $catid, PDO::PARAM_INT);
+ $stmt->execute();
+ $ccats = ($stmt->rowCount() > 0);
+// var_dump($stmt->rowCount());
+// var_dump($stmt->fetch());
+// exit;
+ if ($ccats) {
+ $sql = "
+ SELECT cc.name, cc.id
+ FROM coupon_category cc
+ JOIN coupon_categories2toolbox_pages cc2tp
+ ON cc.id = cc2tp.category
+ JOIN coupons c
+ on c.category = cc.name
+ WHERE cc2tp.page = :catid
+ ORDER BY cc.name";
+ } else {
+ $sql = "
+ SELECT cc.name, cc.id
+ FROM coupon_category cc
+ JOIN coupons c
+ on c.category = cc.name
+ ORDER BY cc.name";
+ }
+
+ $categories = array();
+ $stmt = $dbh->prepare($sql);
+ if ($ccats) {
+ $stmt->bindParam(':catid', $catid, PDO::PARAM_INT);
+ }
+ $stmt->execute();
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $categories[$row['id']] = $row['name'];
+ }
+
+ return $categories;
+ } catch (PDOException $e) {
+ Toolkit_Logger::logException('DB Error', $e);
+ throw new Toolkit_Coupons_Exception('Error retrieving categories');
+ }
+ }
+
+ // }}}
+}
+?>
--- /dev/null
+<?php
+/**
+ * WebCoupon.php
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Coupons
+ * @author Jamie Kahgee <steve@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link <>
+ */
+
+/**
+ * Toolkit_Coupons_WebCoupon
+ *
+ * Description for Toolkit_Coupons_WebCoupon
+ *
+ * @category Toolkit
+ * @package Coupons
+ * @author Jamie Kahgee <steve@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link <>
+ */
+class Toolkit_Coupons_WebCoupon extends Toolkit_Coupons_Coupon
+ implements Toolkit_Coupons_ICoupon, Toolkit_Coupons_IHtmlElement
+{
+ // {{{ properties
+
+ /**
+ * Description for $id
+ * @var int
+ * @access protected
+ */
+ protected $id;
+
+ /**
+ * Description for $sdate
+ * @var date
+ * @access protected
+ */
+ protected $sdate;
+
+ /**
+ * Description for $edate
+ * @var date
+ * @access protected
+ */
+ protected $edate;
+
+ /**
+ * Description for $url
+ * @var string
+ * @access protected
+ */
+ protected $url;
+
+ /**
+ * Description for $active
+ * @var boolean
+ * @access protected
+ */
+ protected $active;
+
+ /**
+ * Description for $category
+ * @var string
+ * @access protected
+ */
+ protected $category;
+
+ /**
+ * Description for $member
+ * @var unknown
+ * @access protected
+ */
+ protected $member;
+
+ // }}}
+ // {{{ __construct()
+ /**
+ * Class constructor
+ *
+ * @param array $data Data array
+ *
+ * @throws InvalidArgumentException
+ * @return void
+ * @access public
+ */
+ public function __construct(array $data)
+ {
+ parent::__construct($data);
+
+ if (isset($data['category']) && !empty($data['category'])) {
+ $this->category = $data['category'];
+ }
+
+ if (isset($data['sdate']) && !empty($data['sdate'])) {
+ if (!($data['sdate'] instanceof Date)) {
+ throw new InvalidArgumentException(
+ 'sdate must be of type Date'
+ );
+ }
+ $this->sdate = $data['sdate'];
+ }
+ if (isset($data['edate']) && !empty($data['edate'])) {
+ if (!($data['edate'] instanceof Date)) {
+ throw new InvalidArgumentException(
+ 'edate must be of type Date'
+ );
+ }
+ $this->edate = $data['edate'];
+ }
+
+ $this->url = $data['url'];
+
+ if (isset($data['id'])) {
+ if (ctype_digit((string)$data['id'])) {
+ settype($data['id'], 'int');
+ $this->id = $data['id'];
+ } else {
+ throw new InvalidArgumentException('id must be an integer');
+ }
+ }
+
+ if (isset($data['active'])) {
+ settype($data['active'], 'bool');
+ $this->active = $data['active'];
+ }
+
+ if (is_numeric($data['member'])) {
+ $this->member = $data['member'];
+ }
+ }
+
+ // }}}
+ // {{{ __toString()
+ // @codeCoverageIgnoreStart
+
+ /**
+ * Convert the coupon object to a HTML string
+ *
+ * @return string HTML output of the coupon
+ * @access public
+ */
+ public function __toString()
+ {
+ $imgUrl = $this->getImage()->getSrc();
+ $imgTpl = '<img alt="%s" src="%s%s">';
+ $img = '';
+ if (!empty($imgUrl)) {
+ $img = sprintf($imgTpl, 'coupon thumbnail', COUPON_THUMB, $imgUrl);
+ }
+
+ $aUrl = $this->getUrl();
+ if (!empty($aUrl)) {
+ $aUrl
+ = (strstr(strtolower($aUrl), 'http://'))
+ ? $aUrl
+ : 'http://' . $aUrl;
+ $aTpl = '<a class="coupon-url" href="%s" target="_blank">Web Site</a>';
+ $anchor = '';
+
+ $anchor = sprintf($aTpl, $aUrl);
+ }
+
+ $desc = nl2br($this->getDescription());
+ $description = '';
+ if (!empty($desc)) {
+ $description = "<p>$desc</p>";
+ }
+ if (defined("MEMBERS_DB") && MEMBERS_DB) {
+ $memberName = $this->getMemberName(
+ Toolkit_Database::getInstance()
+ );
+ if (!empty($memberName)) {
+ $memberName = "$memberName<br>";
+ }
+ }
+
+ $chkBoxTpl = '<input type="checkbox" name="coupon_%d" value="T">';
+ $chkBox = sprintf($chkBoxTpl, $this->getId());
+
+ $out = '<div class="couponitem">';
+ $out .= '<div class="oldBackground">';
+ $out .= '<label class="changeParent">';
+ $out .= $chkBox;
+ $out .= 'Select this coupon';
+ $out .= '</label>';
+ $out .= '</div>';
+ $out .= '<strong>';
+ $out .= $memberName;
+ $out .= $this->getTitle();
+ $out .= '</strong>';
+ $out .= $img;
+ $out .= $description;
+ $out .= $anchor;
+ $out .= '<div class="expire_date">';
+ $out .= 'Expires: ';
+ $out .= $this->getExpiration()->format('%m/%d/%Y');
+ $out .= '</div>';
+ $out .= '</div>';
+
+ return $out;
+ }
+
+ // @codeCoverageIgnoreEnd
+ // }}}
+
+ // {{{ compareDates()
+ /**
+ * Compare the dates so they make sense
+ * 1. end date should be equal to or later than start date
+ * 2. expiration date should be equal to or later than end date
+ *
+ * @access public
+ * @return string
+ */
+ function compareDates()
+ {
+ if ($this->sdate && $this->edate) {
+ if (!(Date::compare($this->sdate, $this->edate) <= 0)) {
+ throw new RuntimeException(
+ 'sdate must be before or equal to edate'
+ );
+ }
+ }
+ if ($this->edate && $this->expiration) {
+ if (!(Date::compare($this->edate, $this->expiration) <= 0)) {
+ throw new RuntimeException(
+ 'expiration must be before or equal to edate'
+ );
+ }
+ }
+ }
+ // }}}
+
+ // {{{ &create()
+ /**
+ * Description for &create()
+ *
+ * @param array $data Data array
+ *
+ * @return \self
+ * @access public
+ * @static
+ */
+ public static function &create(array $data)
+ {
+ return new self($data);
+ }
+
+ // }}}
+
+ // {{{ delete()
+
+ /**
+ * Deletes a Coupon
+ *
+ * @param PDO $dbh Database handler
+ * @param Toolkit_Image_Server $is Image Server
+ *
+ * @return mixed true on sucess, false on error
+ * @access public
+ * @throws RuntimeException if the image server cannot delete the image
+ */
+ public function delete(PDO $dbh, Toolkit_Image_Server $is)
+ {
+ try {
+ if (!is_int($this->id)) {
+ throw new RuntimeException('Coupon not set');
+ }
+ } catch (RuntimeException $e) {
+ Toolkit_Logger::logException('Runtime Error', $e);
+ throw new Toolkit_Coupons_Exception('Error deleting coupon');
+ }
+
+ try {
+ $dbh->beginTransaction();
+
+ $sql = "
+ DELETE from coupons
+ WHERE id = :id";
+
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(':id', $this->id, PDO::PARAM_INT);
+ if ($stmt->execute()) {
+ // make sure we have an image to delete
+ $img = $this->image->getSrc();
+ if (!empty($img) && !$is->imageDelete($img)) {
+ throw new RuntimeException(
+ 'Unable to delete coupon image.'
+ );
+ }
+ }
+
+ return $dbh->commit();
+ } catch (PDOException $e) {
+ $dbh->rollBack();
+ Toolkit_Logger::logException('DB Error', $e);
+ throw new Toolkit_Coupons_Exception('Error deleting coupon');
+ } catch (RuntimeException $e) {
+ $dbh->commit();
+ Toolkit_Logger::logException('Image Server', $e);
+ throw new Toolkit_Coupons_Exception(
+ "Error deleting coupon image [$this->image]"
+ );
+ }
+ }
+
+ // }}}
+
+ // {{{ &fetch()
+
+ /**
+ * Fetch an instance of a coupon by db id
+ *
+ * @param PDO $dbh Database handler
+ * @param integer $id ID of coupon to fetch
+ *
+ * @return Toolkit_Coupons_MemberCoupon concrete coupon
+ * @throws Toolkit_Coupons_Exception on invalid argument or pdo exception
+ * @access public
+ * @static
+ */
+ public static function &fetch(PDO $dbh, $id)
+ {
+ try {
+ if (!ctype_digit((string)$id)) {
+ throw new InvalidArgumentException(
+ "\$id must be an integer [$id] given"
+ );
+ }
+ $sql = "
+ SELECT *
+ FROM coupons
+ WHERE id = :id";
+
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(':id', $id, PDO::PARAM_INT);
+ $stmt->execute();
+
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ if (!$row) {
+ return false; // no coupon found.
+ }
+
+ $row['image'] = Toolkit_Coupons_ImageFactory::getImage($row);
+ $row['sdate']
+ = new Date(strtotime($row['sdate']), DATE_FORMAT_UNIXTIME);
+ $row['edate']
+ = new Date(strtotime($row['edate']), DATE_FORMAT_UNIXTIME);
+ $row['expiration']
+ = new Date(strtotime($row['expiration']), DATE_FORMAT_UNIXTIME);
+ $row['member'] = $row['member'];
+
+ return new self($row);
+ } catch (InvalidArgumentException $e) {
+ Toolkit_Logger::logException('Invalid Arg', $e);
+ throw new Toolkit_Coupons_Exception('Error fetching coupon');
+ } catch (PDOException $e) {
+ Toolkit_Logger::logException('DB Error', $e);
+ throw new Toolkit_Coupons_Exception('Error fetching coupon');
+ }
+ }
+
+ // }}}
+
+ // {{{ getActive()
+
+ /**
+ * Description for getActive()
+ *
+ * @return boolean
+ * @access public
+ */
+ public function getActive()
+ {
+ return $this->active;
+ }
+
+ // }}}
+ // {{{ getCategory()
+
+ /**
+ * Description for getCategory()
+ *
+ * @return string
+ * @access public
+ */
+ public function getCategory()
+ {
+ return $this->category;
+ }
+
+ // }}}
+ // {{{ getEdate()
+
+ /**
+ * Description for getEdate()
+ *
+ * @return date
+ * @access public
+ */
+ public function getEdate()
+ {
+ return $this->edate;
+ }
+
+ // }}}
+ // {{{ getId()
+
+ /**
+ * Description for getId()
+ *
+ * @return int
+ * @access public
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ // }}}
+
+ /**
+ * Description for getMember()
+ *
+ * @return boolean
+ * @access public
+ */
+ public function getMember()
+ {
+ return $this->member;
+ }
+
+ /**
+ * Description for getMemberName()
+ *
+ * @param PDO $dbh Database Handler
+ *
+ * @return string
+ * @access public
+ */
+ public function getMemberName(PDO $dbh)
+ {
+ $sql = "
+ SELECT member_name
+ FROM member
+ WHERE member_id = :member_id";
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(
+ ':member_id',
+ $this->getMember(),
+ PDO::PARAM_INT
+ );
+ $stmt->execute();
+ return $stmt->fetchColumn();
+ }
+ // {{{ getSdate()
+
+ /**
+ * Description of getSdate()
+ *
+ * @return date
+ * @access public
+ */
+ public function getSdate()
+ {
+ return $this->sdate;
+ }
+
+ // }}}
+ // {{{ getUrl()
+
+ /**
+ * Description of getUrl()
+ *
+ * @return string
+ * @access public
+ */
+ public function getUrl()
+ {
+ return $this->url;
+ }
+
+ // }}}
+
+ // {{{ save()
+
+ /**
+ * Description of save()
+ *
+ * @param PDO $dbh Database handler
+ *
+ * @return boolean
+ * @throws Toolkit_Coupons_Exception
+ * @access public
+ */
+ public function save(PDO $dbh)
+ {
+ $classData = get_object_vars($this);
+ if ($classData['image'] instanceof Toolkit_Coupons_Image) {
+ $classData['image'] = $this->image->getSrc();
+ }
+ if ($classData['expiration'] instanceof Date) {
+ $classData['expiration'] = $this->expiration->format('%m-%d-%Y');
+ }
+ if ($classData['sdate'] instanceof Date) {
+ $classData['sdate'] = $this->sdate->format('%m-%d-%Y');
+ }
+ if ($classData['edate'] instanceof Date) {
+ $classData['edate'] = $this->edate->format('%m-%d-%Y');
+ }
+
+ unset($classData['id']); // don't need the id when saving
+ if (defined('MEMBERS_DB') && !MEMBERS_DB) {
+ unset($classData['member']);
+ }
+ $insertSql = Toolkit_Common::createSQLInsert(
+ 'coupons',
+ array_keys($classData)
+ );
+ if (isset($classData['member']) && !$classData['member']) {
+ unset($classData['member']);
+ }
+
+ try {
+ $dbh->beginTransaction();
+ $stmt = Toolkit_Common::prepareQuery(
+ $dbh,
+ 'coupons',
+ $insertSql,
+ $classData
+ );
+ $stmt->execute();
+
+ $fetchSql = "
+ SELECT id
+ FROM coupons
+ ORDER BY id DESC LIMIT 1";
+
+ $row = $dbh->query($fetchSql, PDO::FETCH_ASSOC)->fetch();
+
+ $dbh->commit();
+
+ settype($row['id'], 'int');
+ $this->id = $row['id'];
+ return $this->id;
+ } catch (PDOException $e) {
+ $dbh->rollback();
+ Toolkit_Logger::logException('DB Error', $e);
+ throw new Toolkit_Coupons_Exception('Error Saving Coupon');
+ }
+
+ return false;
+ }
+
+ // }}}
+ // {{{ setActive()
+
+ /**
+ * Description of setActive()
+ *
+ * @param boolean $active Active boolean
+ *
+ * @return boolean
+ * @access public
+ */
+ public function setActive($active)
+ {
+ settype($active, 'bool');
+ $this->active = $active;
+ }
+
+ // }}}
+ // {{{ setCategory()
+
+ /**
+ * Description of setCategory
+ *
+ * @param string $category Coupon category
+ *
+ * @return string
+ * @access public
+ */
+ public function setCategory($category)
+ {
+ $this->category = $category;
+ }
+
+ // }}}
+ // {{{ setEdate()
+
+ /**
+ * Description of setEdate()
+ *
+ * @param Date $edate Coupon end date
+ *
+ * @return boolean
+ * @access public
+ * @throws RuntimeException
+ */
+ public function setEdate(Date $edate)
+ {
+ $this->edate = $edate;
+ return true;
+ if (Date::compare($this->sdate, $edate) <= 0) {
+ $this->edate = $edate;
+ } else {
+ Toolkit_Logger::logException('Runtime Error', $e);
+ throw new RuntimeException(
+ 'edate must be after or equal to sdate'
+ );
+ }
+ }
+
+ // }}}
+ // {{{ setExpriration()
+
+ /**
+ * Description of setExpiration()
+ *
+ * @param Date $expiration Coupon expiration date
+ *
+ * @return boolean
+ * @throws RuntimeException
+ * @access public
+ */
+ public function setExpiration(Date $expiration)
+ {
+ parent::setExpiration($expiration);
+ return true;
+ if (Date::compare($this->edate, $expiration) <= 0) {
+ parent::setExpiration($expiration);
+ } else {
+ throw new RuntimeException(
+ 'expiration must be before or equal to edate'
+ );
+ }
+ }
+
+ // }}}
+ // {{{ setSdate()
+
+ /**
+ * Description for setSdate()
+ *
+ * @param Date $sdate Coupon start date
+ *
+ * @return boolean
+ * @throws RuntimeException
+ * @access public
+ */
+ public function setSdate(Date $sdate)
+ {
+ $this->sdate = $sdate;
+ return true;
+ if (Date::compare($sdate, $this->edate) <= 0) {
+ $this->sdate = $sdate;
+ } else {
+ throw new RuntimeException(
+ 'sdate must be before or equal to edate'
+ );
+ }
+ }
+
+ // }}}
+ // {{{ setUrl()
+
+ /**
+ * Description of setUrl()
+ *
+ * @param string $url Description for $url
+ *
+ * @return void
+ * @access public
+ */
+ public function setUrl($url)
+ {
+ $this->url = $url;
+ }
+
+ // }}}
+
+ // {{{ update()
+
+ /**
+ * Description for update()
+ *
+ * @param PDO $dbh Database handler
+ * @param array $data Data array
+ *
+ * @return boolean
+ * @throws Toolkit_Coupons_Exception
+ * @throws RuntimeException
+ * @access public
+ */
+ public function update(PDO $dbh, array $data)
+ {
+ // need to wipe out the dates before we update both dates
+ $oldSdate = $this->sdate;
+ $oldEdate = $this->edate;
+ //echo '<pre>'.print_r($this, true).'</pre>';
+ $this->sdate = $this->edate = null;
+ if (isset($data['sdate'])) {
+ if ($data['sdate'] instanceof Date) {
+ $this->setSdate($data['sdate']);
+ }
+ }
+ if (isset($data['edate'])) {
+ if ($data['edate'] instanceof Date) {
+ $this->setEdate($data['edate']);
+ }
+ }
+ if (isset($data['expiration'])) {
+ if ($data['expiration'] instanceof Date) {
+ $this->setExpiration($data['expiration']);
+ }
+ }
+ $this->compareDates();
+ if (empty($this->sdate)) {
+ $this->sdate = $oldSdate;
+ }
+ if (empty($this->edate)) {
+ $this->edate = $oldEdate;
+ }
+
+ if (isset($data['url'])) {
+ $this->setUrl($data['url']);
+ }
+ if (isset($data['active'])) {
+ $this->setActive($data['active']);
+ }
+ if (isset($data['category'])) {
+ $this->setCategory($data['category']);
+ }
+ parent::update($data);
+ try {
+ if (!is_int($this->id)) {
+ throw new RuntimeException(
+ '$id is not set. cannot update coupon'
+ );
+ }
+
+ $classData = get_object_vars($this);
+ if (defined('MEMBERS_DB') && !MEMBERS_DB) {
+ unset($classData['member']);
+ }
+ $classData['image'] = ($data['image']) ? $this->image->getSrc(): '';
+ $classData['sdate'] = $this->sdate->format('%m-%d-%Y');
+ $classData['edate'] = $this->edate->format('%m-%d-%Y');
+ $classData['expiration'] = $this->expiration->format('%m-%d-%Y');
+
+ $sql = Toolkit_Common::createSQLUpdate(
+ 'coupons',
+ array_keys($classData),
+ array('id = :id')
+ );
+
+ $stmt = Toolkit_Common::prepareQuery(
+ $dbh,
+ 'coupons',
+ $sql,
+ $classData
+ );
+ return $stmt->execute();
+ } catch (PDOException $e) {
+ Toolkit_Logger::logException('DB Error', $e);
+ throw new Toolkit_Coupons_Exception('Error updating coupon');
+ } catch (RuntimeException $e) {
+ Toolkit_Logger::logException('Runtime Error', $e);
+ throw new Toolkit_Coupons_Exception('Coupon not set');
+ }
+
+ return false;
+ }
+
+ // }}}
+}
\ No newline at end of file
--- /dev/null
+<?php
+class Toolkit_Coupons_WebCouponFactory extends Toolkit_Coupons_CouponFactory
+ implements Toolkit_Coupons_ICouponFactory
+{
+ public function createCoupon(array $c)
+ {
+ return Toolkit_Coupons_WebCoupon::create($c);
+ }
+
+ public function &fetch(PDO $dbh, $id)
+ {
+ return Toolkit_Coupons_WebCoupon::fetch($dbh, $id);
+ }
+}
+?>
--- /dev/null
+<?php\r
+\r
+include_once('class.pdf.php');\r
+\r
+class Cezpdf extends Cpdf {\r
+//==============================================================================\r
+// this class will take the basic interaction facilities of the Cpdf class\r
+// and make more useful functions so that the user does not have to \r
+// know all the ins and outs of pdf presentation to produce something pretty.\r
+//\r
+// IMPORTANT NOTE\r
+// there is no warranty, implied or otherwise with this software.\r
+// \r
+// version 009 (versioning is linked to class.pdf.php)\r
+//\r
+// released under a public domain licence.\r
+//\r
+// Wayne Munro, R&OS Ltd, http://www.ros.co.nz/pdf\r
+//==============================================================================\r
+\r
+var $ez=array('fontSize'=>10); // used for storing most of the page configuration parameters\r
+var $y; // this is the current vertical positon on the page of the writing point, very important\r
+var $ezPages=array(); // keep an array of the ids of the pages, making it easy to go back and add page numbers etc.\r
+var $ezPageCount=0;\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function Cezpdf($paper='a4',$orientation='portrait'){\r
+ // Assuming that people don't want to specify the paper size using the absolute coordinates\r
+ // allow a couple of options:\r
+ // orientation can be 'portrait' or 'landscape'\r
+ // or, to actually set the coordinates, then pass an array in as the first parameter.\r
+ // the defaults are as shown.\r
+ // \r
+ // -------------------------\r
+ // 2002-07-24 - Nicola Asuni (info@tecnick.com):\r
+ // Added new page formats (45 standard ISO paper formats and 4 american common formats)\r
+ // paper cordinates are calculated in this way: (inches * 72) where 1 inch = 2.54 cm\r
+ // \r
+ // Now you may also pass a 2 values array containing the page width and height in centimeters\r
+ // -------------------------\r
+\r
+ if (!is_array($paper)){\r
+ switch (strtoupper($paper)){\r
+ case '4A0': {$size = array(0,0,4767.87,6740.79); break;}\r
+ case '2A0': {$size = array(0,0,3370.39,4767.87); break;}\r
+ case 'A0': {$size = array(0,0,2383.94,3370.39); break;}\r
+ case 'A1': {$size = array(0,0,1683.78,2383.94); break;}\r
+ case 'A2': {$size = array(0,0,1190.55,1683.78); break;}\r
+ case 'A3': {$size = array(0,0,841.89,1190.55); break;}\r
+ case 'A4': default: {$size = array(0,0,595.28,841.89); break;}\r
+ case 'A5': {$size = array(0,0,419.53,595.28); break;}\r
+ case 'A6': {$size = array(0,0,297.64,419.53); break;}\r
+ case 'A7': {$size = array(0,0,209.76,297.64); break;}\r
+ case 'A8': {$size = array(0,0,147.40,209.76); break;}\r
+ case 'A9': {$size = array(0,0,104.88,147.40); break;}\r
+ case 'A10': {$size = array(0,0,73.70,104.88); break;}\r
+ case 'B0': {$size = array(0,0,2834.65,4008.19); break;}\r
+ case 'B1': {$size = array(0,0,2004.09,2834.65); break;}\r
+ case 'B2': {$size = array(0,0,1417.32,2004.09); break;}\r
+ case 'B3': {$size = array(0,0,1000.63,1417.32); break;}\r
+ case 'B4': {$size = array(0,0,708.66,1000.63); break;}\r
+ case 'B5': {$size = array(0,0,498.90,708.66); break;}\r
+ case 'B6': {$size = array(0,0,354.33,498.90); break;}\r
+ case 'B7': {$size = array(0,0,249.45,354.33); break;}\r
+ case 'B8': {$size = array(0,0,175.75,249.45); break;}\r
+ case 'B9': {$size = array(0,0,124.72,175.75); break;}\r
+ case 'B10': {$size = array(0,0,87.87,124.72); break;}\r
+ case 'C0': {$size = array(0,0,2599.37,3676.54); break;}\r
+ case 'C1': {$size = array(0,0,1836.85,2599.37); break;}\r
+ case 'C2': {$size = array(0,0,1298.27,1836.85); break;}\r
+ case 'C3': {$size = array(0,0,918.43,1298.27); break;}\r
+ case 'C4': {$size = array(0,0,649.13,918.43); break;}\r
+ case 'C5': {$size = array(0,0,459.21,649.13); break;}\r
+ case 'C6': {$size = array(0,0,323.15,459.21); break;}\r
+ case 'C7': {$size = array(0,0,229.61,323.15); break;}\r
+ case 'C8': {$size = array(0,0,161.57,229.61); break;}\r
+ case 'C9': {$size = array(0,0,113.39,161.57); break;}\r
+ case 'C10': {$size = array(0,0,79.37,113.39); break;}\r
+ case 'RA0': {$size = array(0,0,2437.80,3458.27); break;}\r
+ case 'RA1': {$size = array(0,0,1729.13,2437.80); break;}\r
+ case 'RA2': {$size = array(0,0,1218.90,1729.13); break;}\r
+ case 'RA3': {$size = array(0,0,864.57,1218.90); break;}\r
+ case 'RA4': {$size = array(0,0,609.45,864.57); break;}\r
+ case 'SRA0': {$size = array(0,0,2551.18,3628.35); break;}\r
+ case 'SRA1': {$size = array(0,0,1814.17,2551.18); break;}\r
+ case 'SRA2': {$size = array(0,0,1275.59,1814.17); break;}\r
+ case 'SRA3': {$size = array(0,0,907.09,1275.59); break;}\r
+ case 'SRA4': {$size = array(0,0,637.80,907.09); break;}\r
+ case 'LETTER': {$size = array(0,0,612.00,792.00); break;}\r
+ case 'LEGAL': {$size = array(0,0,612.00,1008.00); break;}\r
+ case 'EXECUTIVE': {$size = array(0,0,521.86,756.00); break;}\r
+ case 'FOLIO': {$size = array(0,0,612.00,936.00); break;}\r
+ }\r
+ switch (strtolower($orientation)){\r
+ case 'landscape':\r
+ $a=$size[3];\r
+ $size[3]=$size[2];\r
+ $size[2]=$a;\r
+ break;\r
+ }\r
+ } else {\r
+ if (count($paper)>2) {\r
+ // then an array was sent it to set the size\r
+ $size = $paper;\r
+ }\r
+ else { //size in centimeters has been passed\r
+ $size[0] = 0;\r
+ $size[1] = 0;\r
+ $size[2] = ( $paper[0] / 2.54 ) * 72;\r
+ $size[3] = ( $paper[1] / 2.54 ) * 72;\r
+ }\r
+ }\r
+ $this->Cpdf($size);\r
+ $this->ez['pageWidth']=$size[2];\r
+ $this->ez['pageHeight']=$size[3];\r
+ \r
+ // also set the margins to some reasonable defaults\r
+ $this->ez['topMargin']=30;\r
+ $this->ez['bottomMargin']=30;\r
+ $this->ez['leftMargin']=30;\r
+ $this->ez['rightMargin']=30;\r
+ \r
+ // set the current writing position to the top of the first page\r
+ $this->y = $this->ez['pageHeight']-$this->ez['topMargin'];\r
+ // and get the ID of the page that was created during the instancing process.\r
+ $this->ezPages[1]=$this->getFirstPageId();\r
+ $this->ezPageCount=1;\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+// 2002-07-24: Nicola Asuni (info@tecnick.com)\r
+// Set Margins in centimeters\r
+function ezSetCmMargins($top,$bottom,$left,$right){\r
+ $top = ( $top / 2.54 ) * 72;\r
+ $bottom = ( $bottom / 2.54 ) * 72;\r
+ $left = ( $left / 2.54 ) * 72;\r
+ $right = ( $right / 2.54 ) * 72;\r
+ $this->ezSetMargins($top,$bottom,$left,$right);\r
+}\r
+// ------------------------------------------------------------------------------\r
+\r
+\r
+function ezColumnsStart($options=array()){\r
+ // start from the current y-position, make the set number of columne\r
+ if (isset($this->ez['columns']) && $this->ez['columns']==1){\r
+ // if we are already in a column mode then just return.\r
+ return;\r
+ }\r
+ $def=array('gap'=>10,'num'=>2);\r
+ foreach($def as $k=>$v){\r
+ if (!isset($options[$k])){\r
+ $options[$k]=$v;\r
+ }\r
+ }\r
+ // setup the columns\r
+ $this->ez['columns']=array('on'=>1,'colNum'=>1);\r
+\r
+ // store the current margins\r
+ $this->ez['columns']['margins']=array(\r
+ $this->ez['leftMargin']\r
+ ,$this->ez['rightMargin']\r
+ ,$this->ez['topMargin']\r
+ ,$this->ez['bottomMargin']\r
+ );\r
+ // and store the settings for the columns\r
+ $this->ez['columns']['options']=$options;\r
+ // then reset the margins to suit the new columns\r
+ // safe enough to assume the first column here, but start from the current y-position\r
+ $this->ez['topMargin']=$this->ez['pageHeight']-$this->y;\r
+ $width=($this->ez['pageWidth']-$this->ez['leftMargin']-$this->ez['rightMargin']-($options['num']-1)*$options['gap'])/$options['num'];\r
+ $this->ez['columns']['width']=$width;\r
+ $this->ez['rightMargin']=$this->ez['pageWidth']-$this->ez['leftMargin']-$width;\r
+ \r
+}\r
+// ------------------------------------------------------------------------------\r
+function ezColumnsStop(){\r
+ if (isset($this->ez['columns']) && $this->ez['columns']['on']==1){\r
+ $this->ez['columns']['on']=0;\r
+ $this->ez['leftMargin']=$this->ez['columns']['margins'][0];\r
+ $this->ez['rightMargin']=$this->ez['columns']['margins'][1];\r
+ $this->ez['topMargin']=$this->ez['columns']['margins'][2];\r
+ $this->ez['bottomMargin']=$this->ez['columns']['margins'][3];\r
+ }\r
+}\r
+// ------------------------------------------------------------------------------\r
+function ezInsertMode($status=1,$pageNum=1,$pos='before'){\r
+ // puts the document into insert mode. new pages are inserted until this is re-called with status=0\r
+ // by default pages wil be inserted at the start of the document\r
+ switch($status){\r
+ case '1':\r
+ if (isset($this->ezPages[$pageNum])){\r
+ $this->ez['insertMode']=1;\r
+ $this->ez['insertOptions']=array('id'=>$this->ezPages[$pageNum],'pos'=>$pos);\r
+ }\r
+ break;\r
+ case '0':\r
+ $this->ez['insertMode']=0;\r
+ break;\r
+ }\r
+}\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezNewPage(){\r
+ $pageRequired=1;\r
+ if (isset($this->ez['columns']) && $this->ez['columns']['on']==1){\r
+ // check if this is just going to a new column\r
+ // increment the column number\r
+//echo 'HERE<br>';\r
+ $this->ez['columns']['colNum']++;\r
+//echo $this->ez['columns']['colNum'].'<br>';\r
+ if ($this->ez['columns']['colNum'] <= $this->ez['columns']['options']['num']){\r
+ // then just reset to the top of the next column\r
+ $pageRequired=0;\r
+ } else {\r
+ $this->ez['columns']['colNum']=1;\r
+ $this->ez['topMargin']=$this->ez['columns']['margins'][2];\r
+ }\r
+\r
+ $width = $this->ez['columns']['width'];\r
+ $this->ez['leftMargin']=$this->ez['columns']['margins'][0]+($this->ez['columns']['colNum']-1)*($this->ez['columns']['options']['gap']+$width);\r
+ $this->ez['rightMargin']=$this->ez['pageWidth']-$this->ez['leftMargin']-$width;\r
+ }\r
+//echo 'left='.$this->ez['leftMargin'].' right='.$this->ez['rightMargin'].'<br>';\r
+\r
+ if ($pageRequired){\r
+ // make a new page, setting the writing point back to the top\r
+ $this->y = $this->ez['pageHeight']-$this->ez['topMargin'];\r
+ // make the new page with a call to the basic class.\r
+ $this->ezPageCount++;\r
+ if (isset($this->ez['insertMode']) && $this->ez['insertMode']==1){\r
+ $id = $this->ezPages[$this->ezPageCount] = $this->newPage(1,$this->ez['insertOptions']['id'],$this->ez['insertOptions']['pos']);\r
+ // then manipulate the insert options so that inserted pages follow each other\r
+ $this->ez['insertOptions']['id']=$id;\r
+ $this->ez['insertOptions']['pos']='after';\r
+ } else {\r
+ $this->ezPages[$this->ezPageCount] = $this->newPage();\r
+ }\r
+ } else {\r
+ $this->y = $this->ez['pageHeight']-$this->ez['topMargin'];\r
+ }\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezSetMargins($top,$bottom,$left,$right){\r
+ // sets the margins to new values\r
+ $this->ez['topMargin']=$top;\r
+ $this->ez['bottomMargin']=$bottom;\r
+ $this->ez['leftMargin']=$left;\r
+ $this->ez['rightMargin']=$right;\r
+ // check to see if this means that the current writing position is outside the \r
+ // writable area\r
+ if ($this->y > $this->ez['pageHeight']-$top){\r
+ // then move y down\r
+ $this->y = $this->ez['pageHeight']-$top;\r
+ }\r
+ if ( $this->y < $bottom){\r
+ // then make a new page\r
+ $this->ezNewPage();\r
+ }\r
+} \r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezGetCurrentPageNumber(){\r
+ // return the strict numbering (1,2,3,4..) number of the current page\r
+ return $this->ezPageCount;\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezStartPageNumbers($x,$y,$size,$pos='left',$pattern='{PAGENUM} of {TOTALPAGENUM}',$num=''){\r
+ // put page numbers on the pages from here.\r
+ // place then on the 'pos' side of the coordinates (x,y).\r
+ // pos can be 'left' or 'right'\r
+ // use the given 'pattern' for display, where (PAGENUM} and {TOTALPAGENUM} are replaced\r
+ // as required.\r
+ // if $num is set, then make the first page this number, the number of total pages will\r
+ // be adjusted to account for this.\r
+ // Adjust this function so that each time you 'start' page numbers then you effectively start a different batch\r
+ // return the number of the batch, so that they can be stopped in a different order if required.\r
+ if (!$pos || !strlen($pos)){\r
+ $pos='left';\r
+ }\r
+ if (!$pattern || !strlen($pattern)){\r
+ $pattern='{PAGENUM} of {TOTALPAGENUM}';\r
+ }\r
+ if (!isset($this->ez['pageNumbering'])){\r
+ $this->ez['pageNumbering']=array();\r
+ }\r
+ $i = count($this->ez['pageNumbering']);\r
+ $this->ez['pageNumbering'][$i][$this->ezPageCount]=array('x'=>$x,'y'=>$y,'pos'=>$pos,'pattern'=>$pattern,'num'=>$num,'size'=>$size);\r
+ return $i;\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezWhatPageNumber($pageNum,$i=0){\r
+ // given a particular generic page number (ie, document numbered sequentially from beginning),\r
+ // return the page number under a particular page numbering scheme ($i)\r
+ $num=0;\r
+ $start=1;\r
+ $startNum=1;\r
+ if (!isset($this->ez['pageNumbering']))\r
+ {\r
+ $this->addMessage('WARNING: page numbering called for and wasn\'t started with ezStartPageNumbers');\r
+ return 0;\r
+ }\r
+ foreach($this->ez['pageNumbering'][$i] as $k=>$v){\r
+ if ($k<=$pageNum){\r
+ if (is_array($v)){\r
+ // start block\r
+ if (strlen($v['num'])){\r
+ // a start was specified\r
+ $start=$v['num'];\r
+ $startNum=$k;\r
+ $num=$pageNum-$startNum+$start;\r
+ }\r
+ } else {\r
+ // stop block\r
+ $num=0;\r
+ }\r
+ }\r
+ }\r
+ return $num;\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezStopPageNumbers($stopTotal=0,$next=0,$i=0){\r
+ // if stopTotal=1 then the totalling of pages for this number will stop too\r
+ // if $next=1, then do this page, but not the next, else do not do this page either\r
+ // if $i is set, then stop that particular pagenumbering sequence.\r
+ if (!isset($this->ez['pageNumbering'])){\r
+ $this->ez['pageNumbering']=array();\r
+ }\r
+ if ($next && isset($this->ez['pageNumbering'][$i][$this->ezPageCount]) && is_array($this->ez['pageNumbering'][$i][$this->ezPageCount])){\r
+ // then this has only just been started, this will over-write the start, and nothing will appear\r
+ // add a special command to the start block, telling it to stop as well\r
+ if ($stopTotal){\r
+ $this->ez['pageNumbering'][$i][$this->ezPageCount]['stoptn']=1;\r
+ } else {\r
+ $this->ez['pageNumbering'][$i][$this->ezPageCount]['stopn']=1;\r
+ }\r
+ } else {\r
+ if ($stopTotal){\r
+ $this->ez['pageNumbering'][$i][$this->ezPageCount]='stopt';\r
+ } else {\r
+ $this->ez['pageNumbering'][$i][$this->ezPageCount]='stop';\r
+ }\r
+ if ($next){\r
+ $this->ez['pageNumbering'][$i][$this->ezPageCount].='n';\r
+ }\r
+ }\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezPRVTpageNumberSearch($lbl,&$tmp){\r
+ foreach($tmp as $i=>$v){\r
+ if (is_array($v)){\r
+ if (isset($v[$lbl])){\r
+ return $i;\r
+ }\r
+ } else {\r
+ if ($v==$lbl){\r
+ return $i;\r
+ }\r
+ }\r
+ }\r
+ return 0;\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezPRVTaddPageNumbers(){\r
+ // this will go through the pageNumbering array and add the page numbers are required\r
+ if (isset($this->ez['pageNumbering'])){\r
+ $totalPages1 = $this->ezPageCount;\r
+ $tmp1=$this->ez['pageNumbering'];\r
+ $status=0;\r
+ foreach($tmp1 as $i=>$tmp){\r
+ // do each of the page numbering systems\r
+ // firstly, find the total pages for this one\r
+ $k = $this->ezPRVTpageNumberSearch('stopt',$tmp);\r
+ if ($k && $k>0){\r
+ $totalPages = $k-1;\r
+ } else {\r
+ $l = $this->ezPRVTpageNumberSearch('stoptn',$tmp);\r
+ if ($l && $l>0){\r
+ $totalPages = $l;\r
+ } else {\r
+ $totalPages = $totalPages1;\r
+ }\r
+ }\r
+ foreach ($this->ezPages as $pageNum=>$id){\r
+ if (isset($tmp[$pageNum])){\r
+ if (is_array($tmp[$pageNum])){\r
+ // then this must be starting page numbers\r
+ $status=1;\r
+ $info = $tmp[$pageNum];\r
+ $info['dnum']=$info['num']-$pageNum;\r
+ // also check for the special case of the numbering stopping and starting on the same page\r
+ if (isset($info['stopn']) || isset($info['stoptn']) ){\r
+ $status=2;\r
+ }\r
+ } else if ($tmp[$pageNum]=='stop' || $tmp[$pageNum]=='stopt'){\r
+ // then we are stopping page numbers\r
+ $status=0;\r
+ } else if ($status==1 && ($tmp[$pageNum]=='stoptn' || $tmp[$pageNum]=='stopn')){\r
+ // then we are stopping page numbers\r
+ $status=2;\r
+ }\r
+ }\r
+ if ($status){\r
+ // then add the page numbering to this page\r
+ if (strlen($info['num'])){\r
+ $num=$pageNum+$info['dnum'];\r
+ } else {\r
+ $num=$pageNum;\r
+ }\r
+ $total = $totalPages+$num-$pageNum;\r
+ $pat = str_replace('{PAGENUM}',$num,$info['pattern']);\r
+ $pat = str_replace('{TOTALPAGENUM}',$total,$pat);\r
+ $this->reopenObject($id);\r
+ switch($info['pos']){\r
+ case 'right':\r
+ $this->addText($info['x'],$info['y'],$info['size'],$pat);\r
+ break;\r
+ default:\r
+ $w=$this->getTextWidth($info['size'],$pat);\r
+ $this->addText($info['x']-$w,$info['y'],$info['size'],$pat);\r
+ break;\r
+ }\r
+ $this->closeObject();\r
+ }\r
+ if ($status==2){\r
+ $status=0;\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezPRVTcleanUp(){\r
+ $this->ezPRVTaddPageNumbers();\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezStream($options=''){\r
+ $this->ezPRVTcleanUp();\r
+ $this->stream($options);\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezOutput($options=0){\r
+ $this->ezPRVTcleanUp();\r
+ return $this->output($options);\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezSetY($y){\r
+ // used to change the vertical position of the writing point.\r
+ $this->y = $y;\r
+ if ( $this->y < $this->ez['bottomMargin']){\r
+ // then make a new page\r
+ $this->ezNewPage();\r
+ }\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezSetDy($dy,$mod=''){\r
+ // used to change the vertical position of the writing point.\r
+ // changes up by a positive increment, so enter a negative number to go\r
+ // down the page\r
+ // if $mod is set to 'makeSpace' and a new page is forced, then the pointed will be moved \r
+ // down on the new page, this will allow space to be reserved for graphics etc.\r
+ $this->y += $dy;\r
+ if ( $this->y < $this->ez['bottomMargin']){\r
+ // then make a new page\r
+ $this->ezNewPage();\r
+ if ($mod=='makeSpace'){\r
+ $this->y += $dy;\r
+ }\r
+ }\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezPrvtTableDrawLines($pos,$gap,$x0,$x1,$y0,$y1,$y2,$col,$inner,$outer,$opt=1){\r
+ $x0=1000;\r
+ $x1=0;\r
+ $this->setStrokeColor($col[0],$col[1],$col[2]);\r
+ $cnt=0;\r
+ $n = count($pos);\r
+ foreach($pos as $x){\r
+ $cnt++;\r
+ if ($cnt==1 || $cnt==$n){\r
+ $this->setLineStyle($outer);\r
+ } else {\r
+ $this->setLineStyle($inner);\r
+ }\r
+ $this->line($x-$gap/2,$y0,$x-$gap/2,$y2);\r
+ if ($x>$x1){ $x1=$x; };\r
+ if ($x<$x0){ $x0=$x; };\r
+ }\r
+ $this->setLineStyle($outer);\r
+ $this->line($x0-$gap/2-$outer/2,$y0,$x1-$gap/2+$outer/2,$y0);\r
+ // only do the second line if it is different to the first, AND each row does not have\r
+ // a line on it.\r
+ if ($y0!=$y1 && $opt<2){\r
+ $this->line($x0-$gap/2,$y1,$x1-$gap/2,$y1);\r
+ }\r
+ $this->line($x0-$gap/2-$outer/2,$y2,$x1-$gap/2+$outer/2,$y2);\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezPrvtTableColumnHeadings($cols,$pos,$maxWidth,$height,$decender,$gap,$size,&$y,$optionsAll=array()){\r
+ // uses ezText to add the text, and returns the height taken by the largest heading\r
+ // this page will move the headings to a new page if they will not fit completely on this one\r
+ // transaction support will be used to implement this\r
+\r
+ if (isset($optionsAll['cols'])){\r
+ $options = $optionsAll['cols'];\r
+ } else {\r
+ $options = array();\r
+ }\r
+ \r
+ $mx=0;\r
+ $startPage = $this->ezPageCount;\r
+ $secondGo=0;\r
+\r
+ // $y is the position at which the top of the table should start, so the base\r
+ // of the first text, is $y-$height-$gap-$decender, but ezText starts by dropping $height\r
+ \r
+ // the return from this function is the total cell height, including gaps, and $y is adjusted\r
+ // to be the postion of the bottom line\r
+ \r
+ // begin the transaction\r
+ $this->transaction('start');\r
+ $ok=0;\r
+// $y-=$gap-$decender;\r
+ $y-=$gap;\r
+ while ($ok==0){\r
+ foreach($cols as $colName=>$colHeading){\r
+ $this->ezSetY($y);\r
+ if (isset($options[$colName]) && isset($options[$colName]['justification'])){\r
+ $justification = $options[$colName]['justification'];\r
+ } else {\r
+ $justification = 'left';\r
+ }\r
+ $this->ezText($colHeading,$size,array('aleft'=> $pos[$colName],'aright'=>($maxWidth[$colName]+$pos[$colName]),'justification'=>$justification));\r
+ $dy = $y-$this->y;\r
+ if ($dy>$mx){\r
+ $mx=$dy;\r
+ }\r
+ }\r
+ $y = $y - $mx - $gap + $decender;\r
+// $y -= $mx-$gap+$decender;\r
+ \r
+ // now, if this has moved to a new page, then abort the transaction, move to a new page, and put it there\r
+ // do not check on the second time around, to avoid an infinite loop\r
+ if ($this->ezPageCount != $startPage && $secondGo==0){\r
+ $this->transaction('rewind');\r
+ $this->ezNewPage();\r
+ $y = $this->y - $gap-$decender;\r
+ $ok=0;\r
+ $secondGo=1;\r
+// $y = $store_y;\r
+ $mx=0;\r
+\r
+ } else {\r
+ $this->transaction('commit');\r
+ $ok=1;\r
+ }\r
+ }\r
+\r
+ return $mx+$gap*2-$decender;\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezPrvtGetTextWidth($size,$text){\r
+ // will calculate the maximum width, taking into account that the text may be broken\r
+ // by line breaks.\r
+ $mx=0;\r
+ $lines = explode("\n",$text);\r
+ foreach ($lines as $line){\r
+ $w = $this->getTextWidth($size,$line);\r
+ if ($w>$mx){\r
+ $mx=$w;\r
+ }\r
+ }\r
+ return $mx;\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezTable(&$data,$cols='',$title='',$options=''){\r
+ // add a table of information to the pdf document\r
+ // $data is a two dimensional array\r
+ // $cols (optional) is an associative array, the keys are the names of the columns from $data\r
+ // to be presented (and in that order), the values are the titles to be given to the columns\r
+ // $title (optional) is the title to be put on the top of the table\r
+ //\r
+ // $options is an associative array which can contain:\r
+ // 'showLines'=> 0,1,2, default is 1 (show outside and top lines only), 2=> lines on each row\r
+ // 'showHeadings' => 0 or 1\r
+ // 'shaded'=> 0,1,2,3 default is 1 (1->alternate lines are shaded, 0->no shading, 2-> both shaded, second uses shadeCol2)\r
+ // 'shadeCol' => (r,g,b) array, defining the colour of the shading, default is (0.8,0.8,0.8)\r
+ // 'shadeCol2' => (r,g,b) array, defining the colour of the shading of the other blocks, default is (0.7,0.7,0.7)\r
+ // 'fontSize' => 10\r
+ // 'textCol' => (r,g,b) array, text colour\r
+ // 'titleFontSize' => 12\r
+ // 'rowGap' => 2 , the space added at the top and bottom of each row, between the text and the lines\r
+ // 'colGap' => 5 , the space on the left and right sides of each cell\r
+ // 'lineCol' => (r,g,b) array, defining the colour of the lines, default, black.\r
+ // 'xPos' => 'left','right','center','centre',or coordinate, reference coordinate in the x-direction\r
+ // 'xOrientation' => 'left','right','center','centre', position of the table w.r.t 'xPos' \r
+ // 'width'=> <number> which will specify the width of the table, if it turns out to not be this\r
+ // wide, then it will stretch the table to fit, if it is wider then each cell will be made\r
+ // proportionalty smaller, and the content may have to wrap.\r
+ // 'maxWidth'=> <number> similar to 'width', but will only make table smaller than it wants to be\r
+ // 'options' => array(<colname>=>array('justification'=>'left','width'=>100,'link'=>linkDataName),<colname>=>....)\r
+ // allow the setting of other paramaters for the individual columns\r
+ // 'minRowSpace'=> the minimum space between the bottom of each row and the bottom margin, in which a new row will be started\r
+ // if it is less, then a new page would be started, default=-100\r
+ // 'innerLineThickness'=>1\r
+ // 'outerLineThickness'=>1\r
+ // 'splitRows'=>0, 0 or 1, whether or not to allow the rows to be split across page boundaries\r
+ // 'protectRows'=>number, the number of rows to hold with the heading on page, ie, if there less than this number of\r
+ // rows on the page, then move the whole lot onto the next page, default=1\r
+ //\r
+ // note that the user will have had to make a font selection already or this will not \r
+ // produce a valid pdf file.\r
+ \r
+ if (!is_array($data)){\r
+ return;\r
+ }\r
+ \r
+ if (!is_array($cols)){\r
+ // take the columns from the first row of the data set\r
+ reset($data);\r
+ list($k,$v)=each($data);\r
+ if (!is_array($v)){\r
+ return;\r
+ }\r
+ $cols=array();\r
+ foreach($v as $k1=>$v1){\r
+ $cols[$k1]=$k1;\r
+ }\r
+ }\r
+ \r
+ if (!is_array($options)){\r
+ $options=array();\r
+ }\r
+\r
+ $defaults = array(\r
+ 'shaded'=>1,'showLines'=>1,'shadeCol'=>array(0.8,0.8,0.8),'shadeCol2'=>array(0.7,0.7,0.7),'fontSize'=>10,'titleFontSize'=>12\r
+ ,'titleGap'=>5,'lineCol'=>array(0,0,0),'gap'=>5,'xPos'=>'centre','xOrientation'=>'centre'\r
+ ,'showHeadings'=>1,'textCol'=>array(0,0,0),'width'=>0,'maxWidth'=>0,'cols'=>array(),'minRowSpace'=>-100,'rowGap'=>2,'colGap'=>5\r
+ ,'innerLineThickness'=>1,'outerLineThickness'=>1,'splitRows'=>0,'protectRows'=>1\r
+ );\r
+\r
+ foreach($defaults as $key=>$value){\r
+ if (is_array($value)){\r
+ if (!isset($options[$key]) || !is_array($options[$key])){\r
+ $options[$key]=$value;\r
+ }\r
+ } else {\r
+ if (!isset($options[$key])){\r
+ $options[$key]=$value;\r
+ }\r
+ }\r
+ }\r
+ $options['gap']=2*$options['colGap'];\r
+ \r
+ $middle = ($this->ez['pageWidth']-$this->ez['rightMargin'])/2+($this->ez['leftMargin'])/2;\r
+ // figure out the maximum widths of the text within each column\r
+ $maxWidth=array();\r
+ foreach($cols as $colName=>$colHeading){\r
+ $maxWidth[$colName]=0;\r
+ }\r
+ // find the maximum cell widths based on the data\r
+ foreach($data as $row){\r
+ foreach($cols as $colName=>$colHeading){\r
+ $w = $this->ezPrvtGetTextWidth($options['fontSize'],(string)$row[$colName])*1.01;\r
+ if ($w > $maxWidth[$colName]){\r
+ $maxWidth[$colName]=$w;\r
+ }\r
+ }\r
+ }\r
+ // and the maximum widths to fit in the headings\r
+ foreach($cols as $colName=>$colTitle){\r
+ $w = $this->ezPrvtGetTextWidth($options['fontSize'],(string)$colTitle)*1.01;\r
+ if ($w > $maxWidth[$colName]){\r
+ $maxWidth[$colName]=$w;\r
+ }\r
+ }\r
+ \r
+ // calculate the start positions of each of the columns\r
+ $pos=array();\r
+ $x=0;\r
+ $t=$x;\r
+ $adjustmentWidth=0;\r
+ $setWidth=0;\r
+ foreach($maxWidth as $colName => $w){\r
+ $pos[$colName]=$t;\r
+ // if the column width has been specified then set that here, also total the\r
+ // width avaliable for adjustment\r
+ if (isset($options['cols'][$colName]) && isset($options['cols'][$colName]['width']) && $options['cols'][$colName]['width']>0){\r
+ $t=$t+$options['cols'][$colName]['width'];\r
+ $maxWidth[$colName] = $options['cols'][$colName]['width']-$options['gap'];\r
+ $setWidth += $options['cols'][$colName]['width'];\r
+ } else {\r
+ $t=$t+$w+$options['gap'];\r
+ $adjustmentWidth += $w;\r
+ $setWidth += $options['gap'];\r
+ }\r
+ }\r
+ $pos['_end_']=$t;\r
+\r
+ // if maxWidth is specified, and the table is too wide, and the width has not been set,\r
+ // then set the width.\r
+ if ($options['width']==0 && $options['maxWidth'] && ($t-$x)>$options['maxWidth']){\r
+ // then need to make this one smaller\r
+ $options['width']=$options['maxWidth'];\r
+ }\r
+\r
+ if ($options['width'] && $adjustmentWidth>0 && $setWidth<$options['width']){\r
+ // first find the current widths of the columns involved in this mystery\r
+ $cols0 = array();\r
+ $cols1 = array();\r
+ $xq=0;\r
+ $presentWidth=0;\r
+ $last='';\r
+ foreach($pos as $colName=>$p){\r
+ if (!isset($options['cols'][$last]) || !isset($options['cols'][$last]['width']) || $options['cols'][$last]['width']<=0){\r
+ if (strlen($last)){\r
+ $cols0[$last]=$p-$xq -$options['gap'];\r
+ $presentWidth += ($p-$xq - $options['gap']);\r
+ }\r
+ } else {\r
+ $cols1[$last]=$p-$xq;\r
+ }\r
+ $last=$colName;\r
+ $xq=$p;\r
+ }\r
+ // $cols0 contains the widths of all the columns which are not set\r
+ $neededWidth = $options['width']-$setWidth;\r
+ // if needed width is negative then add it equally to each column, else get more tricky\r
+ if ($presentWidth<$neededWidth){\r
+ foreach($cols0 as $colName=>$w){\r
+ $cols0[$colName]+= ($neededWidth-$presentWidth)/count($cols0);\r
+ }\r
+ } else {\r
+ \r
+ $cnt=0;\r
+ while ($presentWidth>$neededWidth && $cnt<100){\r
+ $cnt++; // insurance policy\r
+ // find the widest columns, and the next to widest width\r
+ $aWidest = array();\r
+ $nWidest=0;\r
+ $widest=0;\r
+ foreach($cols0 as $colName=>$w){\r
+ if ($w>$widest){\r
+ $aWidest=array($colName);\r
+ $nWidest = $widest;\r
+ $widest=$w;\r
+ } else if ($w==$widest){\r
+ $aWidest[]=$colName;\r
+ }\r
+ }\r
+ // then figure out what the width of the widest columns would have to be to take up all the slack\r
+ $newWidestWidth = $widest - ($presentWidth-$neededWidth)/count($aWidest);\r
+ if ($newWidestWidth > $nWidest){\r
+ // then there is space to set them to this\r
+ foreach($aWidest as $colName){\r
+ $cols0[$colName] = $newWidestWidth;\r
+ }\r
+ $presentWidth=$neededWidth;\r
+ } else {\r
+ // there is not space, reduce the size of the widest ones down to the next size down, and we\r
+ // will go round again\r
+ foreach($aWidest as $colName){\r
+ $cols0[$colName] = $nWidest;\r
+ }\r
+ $presentWidth=$presentWidth-($widest-$nWidest)*count($aWidest);\r
+ }\r
+ }\r
+ }\r
+ // $cols0 now contains the new widths of the constrained columns.\r
+ // now need to update the $pos and $maxWidth arrays\r
+ $xq=0;\r
+ foreach($pos as $colName=>$p){\r
+ $pos[$colName]=$xq;\r
+ if (!isset($options['cols'][$colName]) || !isset($options['cols'][$colName]['width']) || $options['cols'][$colName]['width']<=0){\r
+ if (isset($cols0[$colName])){\r
+ $xq += $cols0[$colName] + $options['gap'];\r
+ $maxWidth[$colName]=$cols0[$colName];\r
+ }\r
+ } else {\r
+ if (isset($cols1[$colName])){\r
+ $xq += $cols1[$colName];\r
+ }\r
+ }\r
+ }\r
+\r
+ $t=$x+$options['width'];\r
+ $pos['_end_']=$t;\r
+ }\r
+\r
+ // now adjust the table to the correct location across the page\r
+ switch ($options['xPos']){\r
+ case 'left':\r
+ $xref = $this->ez['leftMargin'];\r
+ break;\r
+ case 'right':\r
+ $xref = $this->ez['pageWidth'] - $this->ez['rightMargin'];\r
+ break;\r
+ case 'centre':\r
+ case 'center':\r
+ $xref = $middle;\r
+ break;\r
+ default:\r
+ $xref = $options['xPos'];\r
+ break;\r
+ }\r
+ switch ($options['xOrientation']){\r
+ case 'left':\r
+ $dx = $xref-$t;\r
+ break;\r
+ case 'right':\r
+ $dx = $xref;\r
+ break;\r
+ case 'centre':\r
+ case 'center':\r
+ $dx = $xref-$t/2;\r
+ break;\r
+ }\r
+\r
+\r
+ foreach($pos as $k=>$v){\r
+ $pos[$k]=$v+$dx;\r
+ }\r
+ $x0=$x+$dx;\r
+ $x1=$t+$dx;\r
+\r
+ $baseLeftMargin = $this->ez['leftMargin'];\r
+ $basePos = $pos;\r
+ $baseX0 = $x0;\r
+ $baseX1 = $x1;\r
+ \r
+ // ok, just about ready to make me a table\r
+ $this->setColor($options['textCol'][0],$options['textCol'][1],$options['textCol'][2]);\r
+ $this->setStrokeColor($options['shadeCol'][0],$options['shadeCol'][1],$options['shadeCol'][2]);\r
+\r
+ $middle = ($x1+$x0)/2;\r
+\r
+ // start a transaction which will be used to regress the table, if there are not enough rows protected\r
+ if ($options['protectRows']>0){\r
+ $this->transaction('start');\r
+ $movedOnce=0;\r
+ }\r
+ $abortTable = 1;\r
+ while ($abortTable){\r
+ $abortTable=0;\r
+\r
+ $dm = $this->ez['leftMargin']-$baseLeftMargin;\r
+ foreach($basePos as $k=>$v){\r
+ $pos[$k]=$v+$dm;\r
+ }\r
+ $x0=$baseX0+$dm;\r
+ $x1=$baseX1+$dm;\r
+ $middle = ($x1+$x0)/2;\r
+\r
+\r
+ // if the title is set, then do that\r
+ if (strlen($title)){\r
+ $w = $this->getTextWidth($options['titleFontSize'],$title);\r
+ $this->y -= $this->getFontHeight($options['titleFontSize']);\r
+ if ($this->y < $this->ez['bottomMargin']){\r
+ $this->ezNewPage();\r
+ // margins may have changed on the newpage\r
+ $dm = $this->ez['leftMargin']-$baseLeftMargin;\r
+ foreach($basePos as $k=>$v){\r
+ $pos[$k]=$v+$dm;\r
+ }\r
+ $x0=$baseX0+$dm;\r
+ $x1=$baseX1+$dm;\r
+ $middle = ($x1+$x0)/2;\r
+ $this->y -= $this->getFontHeight($options['titleFontSize']);\r
+ }\r
+ $this->addText($middle-$w/2,$this->y,$options['titleFontSize'],$title);\r
+ $this->y -= $options['titleGap'];\r
+ }\r
+\r
+ // margins may have changed on the newpage\r
+ $dm = $this->ez['leftMargin']-$baseLeftMargin;\r
+ foreach($basePos as $k=>$v){\r
+ $pos[$k]=$v+$dm;\r
+ }\r
+ $x0=$baseX0+$dm;\r
+ $x1=$baseX1+$dm;\r
+ \r
+ $y=$this->y; // to simplify the code a bit\r
+ \r
+ // make the table\r
+ $height = $this->getFontHeight($options['fontSize']);\r
+ $decender = $this->getFontDecender($options['fontSize']);\r
+\r
+ \r
+ \r
+ $y0=$y+$decender;\r
+ $dy=0;\r
+ if ($options['showHeadings']){\r
+ // this function will move the start of the table to a new page if it does not fit on this one\r
+ $headingHeight = $this->ezPrvtTableColumnHeadings($cols,$pos,$maxWidth,$height,$decender,$options['rowGap'],$options['fontSize'],$y,$options);\r
+ $y0 = $y+$headingHeight;\r
+ $y1 = $y;\r
+\r
+\r
+ $dm = $this->ez['leftMargin']-$baseLeftMargin;\r
+ foreach($basePos as $k=>$v){\r
+ $pos[$k]=$v+$dm;\r
+ }\r
+ $x0=$baseX0+$dm;\r
+ $x1=$baseX1+$dm;\r
+\r
+ } else {\r
+ $y1 = $y0;\r
+ }\r
+ $firstLine=1;\r
+\r
+ \r
+ // open an object here so that the text can be put in over the shading\r
+ if ($options['shaded']){\r
+ $this->saveState();\r
+ $textObjectId = $this->openObject();\r
+ $this->closeObject();\r
+ $this->addObject($textObjectId);\r
+ $this->reopenObject($textObjectId);\r
+ }\r
+ \r
+ $cnt=0;\r
+ $newPage=0;\r
+ foreach($data as $row){\r
+ $cnt++;\r
+ // the transaction support will be used to prevent rows being split\r
+ if ($options['splitRows']==0){\r
+ $pageStart = $this->ezPageCount;\r
+ if (isset($this->ez['columns']) && $this->ez['columns']['on']==1){\r
+ $columnStart = $this->ez['columns']['colNum'];\r
+ }\r
+ $this->transaction('start');\r
+ $row_orig = $row;\r
+ $y_orig = $y;\r
+ $y0_orig = $y0;\r
+ $y1_orig = $y1;\r
+ }\r
+ $ok=0;\r
+ $secondTurn=0;\r
+ while(!$abortTable && $ok == 0){\r
+\r
+ $mx=0;\r
+ $newRow=1;\r
+ while(!$abortTable && ($newPage || $newRow)){\r
+ \r
+ $y-=$height;\r
+ if ($newPage || $y<$this->ez['bottomMargin'] || (isset($options['minRowSpace']) && $y<($this->ez['bottomMargin']+$options['minRowSpace'])) ){\r
+ // check that enough rows are with the heading\r
+ if ($options['protectRows']>0 && $movedOnce==0 && $cnt<=$options['protectRows']){\r
+ // then we need to move the whole table onto the next page\r
+ $movedOnce = 1;\r
+ $abortTable = 1;\r
+ }\r
+ \r
+ $y2=$y-$mx+2*$height+$decender-$newRow*$height;\r
+ if ($options['showLines']){\r
+ if (!$options['showHeadings']){\r
+ $y0=$y1;\r
+ }\r
+ $this->ezPrvtTableDrawLines($pos,$options['gap'],$x0,$x1,$y0,$y1,$y2,$options['lineCol'],$options['innerLineThickness'],$options['outerLineThickness'],$options['showLines']);\r
+ }\r
+ if ($options['shaded']){\r
+ $this->closeObject();\r
+ $this->restoreState();\r
+ }\r
+ $this->ezNewPage();\r
+ // and the margins may have changed, this is due to the possibility of the columns being turned on\r
+ // as the columns are managed by manipulating the margins\r
+\r
+ $dm = $this->ez['leftMargin']-$baseLeftMargin;\r
+ foreach($basePos as $k=>$v){\r
+ $pos[$k]=$v+$dm;\r
+ }\r
+// $x0=$x0+$dm;\r
+// $x1=$x1+$dm;\r
+ $x0=$baseX0+$dm;\r
+ $x1=$baseX1+$dm;\r
+ \r
+ if ($options['shaded']){\r
+ $this->saveState();\r
+ $textObjectId = $this->openObject();\r
+ $this->closeObject();\r
+ $this->addObject($textObjectId);\r
+ $this->reopenObject($textObjectId);\r
+ }\r
+ $this->setColor($options['textCol'][0],$options['textCol'][1],$options['textCol'][2],1);\r
+ $y = $this->ez['pageHeight']-$this->ez['topMargin'];\r
+ $y0=$y+$decender;\r
+ $mx=0;\r
+ if ($options['showHeadings']){\r
+ $this->ezPrvtTableColumnHeadings($cols,$pos,$maxWidth,$height,$decender,$options['rowGap'],$options['fontSize'],$y,$options);\r
+ $y1=$y;\r
+ } else {\r
+ $y1=$y0;\r
+ }\r
+ $firstLine=1;\r
+ $y -= $height;\r
+ }\r
+ $newRow=0;\r
+ // write the actual data\r
+ // if these cells need to be split over a page, then $newPage will be set, and the remaining\r
+ // text will be placed in $leftOvers\r
+ $newPage=0;\r
+ $leftOvers=array();\r
+\r
+ foreach($cols as $colName=>$colTitle){\r
+ $this->ezSetY($y+$height);\r
+ $colNewPage=0;\r
+ if (isset($row[$colName])){\r
+ if (isset($options['cols'][$colName]) && isset($options['cols'][$colName]['link']) && strlen($options['cols'][$colName]['link'])){\r
+ \r
+ $lines = explode("\n",$row[$colName]);\r
+ if (isset($row[$options['cols'][$colName]['link']]) && strlen($row[$options['cols'][$colName]['link']])){\r
+ foreach($lines as $k=>$v){\r
+ $lines[$k]='<c:alink:'.$row[$options['cols'][$colName]['link']].'>'.$v.'</c:alink>';\r
+ }\r
+ }\r
+ } else {\r
+ $lines = explode("\n",$row[$colName]);\r
+ }\r
+ } else {\r
+ $lines = array();\r
+ }\r
+ $this->y -= $options['rowGap'];\r
+ foreach ($lines as $line){\r
+ $line = $this->ezProcessText($line);\r
+ $start=1;\r
+\r
+ while (strlen($line) || $start){\r
+ $start=0;\r
+ if (!$colNewPage){\r
+ $this->y=$this->y-$height;\r
+ }\r
+ if ($this->y < $this->ez['bottomMargin']){\r
+ // $this->ezNewPage();\r
+ $newPage=1; // whether a new page is required for any of the columns\r
+ $colNewPage=1; // whether a new page is required for this column\r
+ }\r
+ if ($colNewPage){\r
+ if (isset($leftOvers[$colName])){\r
+ $leftOvers[$colName].="\n".$line;\r
+ } else {\r
+ $leftOvers[$colName] = $line;\r
+ }\r
+ $line='';\r
+ } else {\r
+ if (isset($options['cols'][$colName]) && isset($options['cols'][$colName]['justification']) ){\r
+ $just = $options['cols'][$colName]['justification'];\r
+ } else {\r
+ $just='left';\r
+ }\r
+\r
+ $line=$this->addTextWrap($pos[$colName],$this->y,$maxWidth[$colName],$options['fontSize'],$line,$just);\r
+ }\r
+ }\r
+ }\r
+ \r
+ $dy=$y+$height-$this->y+$options['rowGap'];\r
+ if ($dy-$height*$newPage>$mx){\r
+ $mx=$dy-$height*$newPage;\r
+ }\r
+ }\r
+ // set $row to $leftOvers so that they will be processed onto the new page\r
+ $row = $leftOvers;\r
+ // now add the shading underneath\r
+ if ($options['shaded'] && $cnt%2==0){\r
+ $this->closeObject();\r
+ $this->setColor($options['shadeCol'][0],$options['shadeCol'][1],$options['shadeCol'][2],1);\r
+ $this->filledRectangle($x0-$options['gap']/2,$y+$decender+$height-$mx,$x1-$x0,$mx);\r
+ $this->reopenObject($textObjectId);\r
+ }\r
+\r
+ if ($options['shaded']==2 && $cnt%2==1){\r
+ $this->closeObject();\r
+ $this->setColor($options['shadeCol2'][0],$options['shadeCol2'][1],$options['shadeCol2'][2],1);\r
+ $this->filledRectangle($x0-$options['gap']/2,$y+$decender+$height-$mx,$x1-$x0,$mx);\r
+ $this->reopenObject($textObjectId);\r
+ }\r
+\r
+ if ($options['showLines']>1){\r
+ // then draw a line on the top of each block\r
+// $this->closeObject();\r
+ $this->saveState();\r
+ $this->setStrokeColor($options['lineCol'][0],$options['lineCol'][1],$options['lineCol'][2],1);\r
+// $this->line($x0-$options['gap']/2,$y+$decender+$height-$mx,$x1-$x0,$mx);\r
+ if ($firstLine){\r
+ $this->setLineStyle($options['outerLineThickness']);\r
+ $firstLine=0;\r
+ } else {\r
+ $this->setLineStyle($options['innerLineThickness']);\r
+ }\r
+ $this->line($x0-$options['gap']/2,$y+$decender+$height,$x1-$options['gap']/2,$y+$decender+$height);\r
+ $this->restoreState();\r
+// $this->reopenObject($textObjectId);\r
+ }\r
+ } // end of while \r
+ $y=$y-$mx+$height;\r
+ \r
+ // checking row split over pages\r
+ if ($options['splitRows']==0){\r
+ if ( ( ($this->ezPageCount != $pageStart) || (isset($this->ez['columns']) && $this->ez['columns']['on']==1 && $columnStart != $this->ez['columns']['colNum'] )) && $secondTurn==0){\r
+ // then we need to go back and try that again !\r
+ $newPage=1;\r
+ $secondTurn=1;\r
+ $this->transaction('rewind');\r
+ $row = $row_orig;\r
+ $y = $y_orig;\r
+ $y0 = $y0_orig;\r
+ $y1 = $y1_orig;\r
+ $ok=0;\r
+\r
+ $dm = $this->ez['leftMargin']-$baseLeftMargin;\r
+ foreach($basePos as $k=>$v){\r
+ $pos[$k]=$v+$dm;\r
+ }\r
+ $x0=$baseX0+$dm;\r
+ $x1=$baseX1+$dm;\r
+\r
+ } else {\r
+ $this->transaction('commit');\r
+ $ok=1;\r
+ }\r
+ } else {\r
+ $ok=1; // don't go round the loop if splitting rows is allowed\r
+ }\r
+ \r
+ } // end of while to check for row splitting\r
+ if ($abortTable){\r
+ if ($ok==0){\r
+ $this->transaction('abort');\r
+ }\r
+ // only the outer transaction should be operational\r
+ $this->transaction('rewind');\r
+ $this->ezNewPage();\r
+ break;\r
+ }\r
+ \r
+ } // end of foreach ($data as $row)\r
+ \r
+ } // end of while ($abortTable)\r
+\r
+ // table has been put on the page, the rows guarded as required, commit.\r
+ $this->transaction('commit');\r
+\r
+ $y2=$y+$decender;\r
+ if ($options['showLines']){\r
+ if (!$options['showHeadings']){\r
+ $y0=$y1;\r
+ }\r
+ $this->ezPrvtTableDrawLines($pos,$options['gap'],$x0,$x1,$y0,$y1,$y2,$options['lineCol'],$options['innerLineThickness'],$options['outerLineThickness'],$options['showLines']);\r
+ }\r
+\r
+ // close the object for drawing the text on top\r
+ if ($options['shaded']){\r
+ $this->closeObject();\r
+ $this->restoreState();\r
+ }\r
+ \r
+ $this->y=$y;\r
+ return $y;\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+function ezProcessText($text){\r
+ // this function will intially be used to implement underlining support, but could be used for a range of other\r
+ // purposes\r
+ $search = array('<u>','<U>','</u>','</U>');\r
+ $replace = array('<c:uline>','<c:uline>','</c:uline>','</c:uline>');\r
+ return str_replace($search,$replace,$text);\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezText($text,$size=0,$options=array(),$test=0){\r
+ // this will add a string of text to the document, starting at the current drawing\r
+ // position.\r
+ // it will wrap to keep within the margins, including optional offsets from the left\r
+ // and the right, if $size is not specified, then it will be the last one used, or\r
+ // the default value (12 I think).\r
+ // the text will go to the start of the next line when a return code "\n" is found.\r
+ // possible options are:\r
+ // 'left'=> number, gap to leave from the left margin\r
+ // 'right'=> number, gap to leave from the right margin\r
+ // 'aleft'=> number, absolute left position (overrides 'left')\r
+ // 'aright'=> number, absolute right position (overrides 'right')\r
+ // 'justification' => 'left','right','center','centre','full'\r
+\r
+ // only set one of the next two items (leading overrides spacing)\r
+ // 'leading' => number, defines the total height taken by the line, independent of the font height.\r
+ // 'spacing' => a real number, though usually set to one of 1, 1.5, 2 (line spacing as used in word processing)\r
+ \r
+ // if $test is set then this should just check if the text is going to flow onto a new page or not, returning true or false\r
+ \r
+ // apply the filtering which will make the underlining function.\r
+ $text = $this->ezProcessText($text);\r
+ \r
+ $newPage=false;\r
+ $store_y = $this->y;\r
+ \r
+ if (is_array($options) && isset($options['aleft'])){\r
+ $left=$options['aleft'];\r
+ } else {\r
+ $left = $this->ez['leftMargin'] + ((is_array($options) && isset($options['left']))?$options['left']:0);\r
+ }\r
+ if (is_array($options) && isset($options['aright'])){\r
+ $right=$options['aright'];\r
+ } else {\r
+ $right = $this->ez['pageWidth'] - $this->ez['rightMargin'] - ((is_array($options) && isset($options['right']))?$options['right']:0);\r
+ }\r
+ if ($size<=0){\r
+ $size = $this->ez['fontSize'];\r
+ } else {\r
+ $this->ez['fontSize']=$size;\r
+ }\r
+ \r
+ if (is_array($options) && isset($options['justification'])){\r
+ $just = $options['justification'];\r
+ } else {\r
+ $just = 'left';\r
+ }\r
+ \r
+ // modifications to give leading and spacing based on those given by Craig Heydenburg 1/1/02\r
+ if (is_array($options) && isset($options['leading'])) { ## use leading instead of spacing\r
+ $height = $options['leading'];\r
+ } else if (is_array($options) && isset($options['spacing'])) {\r
+ $height = $this->getFontHeight($size) * $options['spacing'];\r
+ } else {\r
+ $height = $this->getFontHeight($size);\r
+ }\r
+\r
+ \r
+ $lines = explode("\n",$text);\r
+ foreach ($lines as $line){\r
+ $start=1;\r
+ while (strlen($line) || $start){\r
+ $start=0;\r
+ $this->y=$this->y-$height;\r
+ if ($this->y < $this->ez['bottomMargin']){\r
+ if ($test){\r
+ $newPage=true;\r
+ } else {\r
+ $this->ezNewPage();\r
+ // and then re-calc the left and right, in case they have changed due to columns\r
+ }\r
+ }\r
+ if (is_array($options) && isset($options['aleft'])){\r
+ $left=$options['aleft'];\r
+ } else {\r
+ $left = $this->ez['leftMargin'] + ((is_array($options) && isset($options['left']))?$options['left']:0);\r
+ }\r
+ if (is_array($options) && isset($options['aright'])){\r
+ $right=$options['aright'];\r
+ } else {\r
+ $right = $this->ez['pageWidth'] - $this->ez['rightMargin'] - ((is_array($options) && isset($options['right']))?$options['right']:0);\r
+ }\r
+ $line=$this->addTextWrap($left,$this->y,$right-$left,$size,$line,$just,0,$test);\r
+ }\r
+ }\r
+\r
+ if ($test){\r
+ $this->y=$store_y;\r
+ return $newPage;\r
+ } else {\r
+ return $this->y;\r
+ }\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function ezImage($image,$pad = 5,$width = 0,$resize = 'full',$just = 'center',$border = ''){\r
+ //beta ezimage function\r
+ if (stristr($image,'://'))//copy to temp file\r
+ {\r
+ $fp = @fopen($image,"rb");\r
+ while(!feof($fp))\r
+ {\r
+ $cont.= fread($fp,1024);\r
+ }\r
+ fclose($fp);\r
+ $image = tempnam ("/tmp", "php-pdf");\r
+ $fp2 = @fopen($image,"w");\r
+ fwrite($fp2,$cont);\r
+ fclose($fp2);\r
+ $temp = true;\r
+ }\r
+\r
+ if (!(file_exists($image))) return false; //return immediately if image file does not exist\r
+ $imageInfo = getimagesize($image);\r
+ switch ($imageInfo[2]){\r
+ case 2:\r
+ $type = "jpeg";\r
+ break;\r
+ case 3:\r
+ $type = "png";\r
+ break;\r
+ default:\r
+ return false; //return if file is not jpg or png\r
+ }\r
+ if ($width == 0) $width = $imageInfo[0]; //set width\r
+ $ratio = $imageInfo[0]/$imageInfo[1];\r
+\r
+ //get maximum width of image\r
+ if (isset($this->ez['columns']) && $this->ez['columns']['on'] == 1)\r
+ {\r
+ $bigwidth = $this->ez['columns']['width'] - ($pad * 2);\r
+ }\r
+ else\r
+ {\r
+ $bigwidth = $this->ez['pageWidth'] - ($pad * 2);\r
+ }\r
+ //fix width if larger than maximum or if $resize=full\r
+ if ($resize == 'full' || $resize == 'width' || $width > $bigwidth)\r
+ {\r
+ $width = $bigwidth;\r
+\r
+ }\r
+\r
+ $height = ($width/$ratio); //set height\r
+\r
+ //fix size if runs off page\r
+ if ($height > ($this->y - $this->ez['bottomMargin'] - ($pad * 2)))\r
+ {\r
+ if ($resize != 'full')\r
+ {\r
+ $this->ezNewPage();\r
+ }\r
+ else\r
+ {\r
+ $height = ($this->y - $this->ez['bottomMargin'] - ($pad * 2)); //shrink height\r
+ $width = ($height*$ratio); //fix width\r
+ }\r
+ }\r
+\r
+ //fix x-offset if image smaller than bigwidth\r
+ if ($width < $bigwidth)\r
+ {\r
+ //center if justification=center\r
+ if ($just == 'center')\r
+ {\r
+ $offset = ($bigwidth - $width) / 2;\r
+ }\r
+ //move to right if justification=right\r
+ if ($just == 'right')\r
+ {\r
+ $offset = ($bigwidth - $width);\r
+ }\r
+ //leave at left if justification=left\r
+ if ($just == 'left')\r
+ {\r
+ $offset = 0;\r
+ }\r
+ }\r
+\r
+\r
+ //call appropriate function\r
+ if ($type == "jpeg"){\r
+ $this->addJpegFromFile($image,$this->ez['leftMargin'] + $pad + $offset, $this->y + $this->getFontHeight($this->ez['fontSize']) - $pad - $height,$width);\r
+ }\r
+\r
+ if ($type == "png"){\r
+ $this->addPngFromFile($image,$this->ez['leftMargin'] + $pad + $offset, $this->y + $this->getFontHeight($this->ez['fontSize']) - $pad - $height,$width);\r
+ }\r
+ //draw border\r
+ if ($border != '')\r
+ {\r
+ if (!(isset($border['color'])))\r
+ {\r
+ $border['color']['red'] = .5;\r
+ $border['color']['blue'] = .5;\r
+ $border['color']['green'] = .5;\r
+ }\r
+ if (!(isset($border['width']))) $border['width'] = 1;\r
+ if (!(isset($border['cap']))) $border['cap'] = 'round';\r
+ if (!(isset($border['join']))) $border['join'] = 'round';\r
+ \r
+\r
+ $this->setStrokeColor($border['color']['red'],$border['color']['green'],$border['color']['blue']);\r
+ $this->setLineStyle($border['width'],$border['cap'],$border['join']);\r
+ $this->rectangle($this->ez['leftMargin'] + $pad + $offset, $this->y + $this->getFontHeight($this->ez['fontSize']) - $pad - $height,$width,$height);\r
+\r
+ }\r
+ // move y below image\r
+ $this->y = $this->y - $pad - $height;\r
+ //remove tempfile for remote images\r
+ if ($temp == true) unlink($image);\r
+\r
+}\r
+// ------------------------------------------------------------------------------\r
+\r
+// note that templating code is still considered developmental - have not really figured\r
+// out a good way of doing this yet.\r
+function loadTemplate($templateFile){\r
+ // this function will load the requested template ($file includes full or relative pathname)\r
+ // the code for the template will be modified to make it name safe, and then stored in \r
+ // an array for later use\r
+ // The id of the template will be returned for the user to operate on it later\r
+ if (!file_exists($templateFile)){\r
+ return -1;\r
+ }\r
+\r
+ $code = implode('',file($templateFile));\r
+ if (!strlen($code)){\r
+ return;\r
+ }\r
+\r
+ $code = trim($code);\r
+ if (substr($code,0,5)=='<?php'){\r
+ $code = substr($code,5);\r
+ }\r
+ if (substr($code,-2)=='?>'){\r
+ $code = substr($code,0,strlen($code)-2);\r
+ }\r
+ if (isset($this->ez['numTemplates'])){\r
+ $newNum = $this->ez['numTemplates'];\r
+ $this->ez['numTemplates']++;\r
+ } else {\r
+ $newNum=0;\r
+ $this->ez['numTemplates']=1;\r
+ $this->ez['templates']=array();\r
+ }\r
+\r
+ $this->ez['templates'][$newNum]['code']=$code;\r
+\r
+ return $newNum;\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function execTemplate($id,$data=array(),$options=array()){\r
+ // execute the given template on the current document.\r
+ if (!isset($this->ez['templates'][$id])){\r
+ return;\r
+ }\r
+ eval($this->ez['templates'][$id]['code']);\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+function ilink($info){\r
+ $this->alink($info,1);\r
+}\r
+\r
+function alink($info,$internal=0){\r
+ // a callback function to support the formation of clickable links within the document\r
+ $lineFactor=0.05; // the thickness of the line as a proportion of the height. also the drop of the line.\r
+ switch($info['status']){\r
+ case 'start':\r
+ case 'sol':\r
+ // the beginning of the link\r
+ // this should contain the URl for the link as the 'p' entry, and will also contain the value of 'nCallback'\r
+ if (!isset($this->ez['links'])){\r
+ $this->ez['links']=array();\r
+ }\r
+ $i = $info['nCallback'];\r
+ $this->ez['links'][$i] = array('x'=>$info['x'],'y'=>$info['y'],'angle'=>$info['angle'],'decender'=>$info['decender'],'height'=>$info['height'],'url'=>$info['p']);\r
+ if ($internal==0){\r
+ $this->saveState();\r
+ $this->setColor(0,0,1);\r
+ $this->setStrokeColor(0,0,1);\r
+ $thick = $info['height']*$lineFactor;\r
+ $this->setLineStyle($thick);\r
+ }\r
+ break;\r
+ case 'end':\r
+ case 'eol':\r
+ // the end of the link\r
+ // assume that it is the most recent opening which has closed\r
+ $i = $info['nCallback'];\r
+ $start = $this->ez['links'][$i];\r
+ // add underlining\r
+ if ($internal){\r
+ $this->addInternalLink($start['url'],$start['x'],$start['y']+$start['decender'],$info['x'],$start['y']+$start['decender']+$start['height']);\r
+ } else {\r
+ $a = deg2rad((float)$start['angle']-90.0);\r
+ $drop = $start['height']*$lineFactor*1.5;\r
+ $dropx = cos($a)*$drop;\r
+ $dropy = -sin($a)*$drop;\r
+ $this->line($start['x']-$dropx,$start['y']-$dropy,$info['x']-$dropx,$info['y']-$dropy);\r
+ $this->addLink($start['url'],$start['x'],$start['y']+$start['decender'],$info['x'],$start['y']+$start['decender']+$start['height']);\r
+ $this->restoreState();\r
+ }\r
+ break;\r
+ }\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+function uline($info){\r
+ // a callback function to support underlining\r
+ $lineFactor=0.05; // the thickness of the line as a proportion of the height. also the drop of the line.\r
+ switch($info['status']){\r
+ case 'start':\r
+ case 'sol':\r
+ \r
+ // the beginning of the underline zone\r
+ if (!isset($this->ez['links'])){\r
+ $this->ez['links']=array();\r
+ }\r
+ $i = $info['nCallback'];\r
+ $this->ez['links'][$i] = array('x'=>$info['x'],'y'=>$info['y'],'angle'=>$info['angle'],'decender'=>$info['decender'],'height'=>$info['height']);\r
+ $this->saveState();\r
+ $thick = $info['height']*$lineFactor;\r
+ $this->setLineStyle($thick);\r
+ break;\r
+ case 'end':\r
+ case 'eol':\r
+ // the end of the link\r
+ // assume that it is the most recent opening which has closed\r
+ $i = $info['nCallback'];\r
+ $start = $this->ez['links'][$i];\r
+ // add underlining\r
+ $a = deg2rad((float)$start['angle']-90.0);\r
+ $drop = $start['height']*$lineFactor*1.5;\r
+ $dropx = cos($a)*$drop;\r
+ $dropy = -sin($a)*$drop;\r
+ $this->line($start['x']-$dropx,$start['y']-$dropy,$info['x']-$dropx,$info['y']-$dropy);\r
+ $this->restoreState();\r
+ break;\r
+ }\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+\r
+}\r
+?>
\ No newline at end of file
--- /dev/null
+<?php\r
+/**\r
+* Cpdf\r
+*\r
+* http://www.ros.co.nz/pdf\r
+*\r
+* A PHP class to provide the basic functionality to create a pdf document without\r
+* any requirement for additional modules.\r
+*\r
+* Note that they companion class CezPdf can be used to extend this class and dramatically\r
+* simplify the creation of documents.\r
+*\r
+* IMPORTANT NOTE\r
+* there is no warranty, implied or otherwise with this software.\r
+* \r
+* LICENCE\r
+* This code has been placed in the Public Domain for all to enjoy.\r
+*\r
+* @author Wayne Munro <pdf@ros.co.nz>\r
+* @version 009\r
+* @package Cpdf\r
+*/\r
+class Cpdf {\r
+\r
+/**\r
+* the current number of pdf objects in the document\r
+*/\r
+var $numObj=0;\r
+/**\r
+* this array contains all of the pdf objects, ready for final assembly\r
+*/\r
+var $objects = array();\r
+/**\r
+* the objectId (number within the objects array) of the document catalog\r
+*/\r
+var $catalogId;\r
+/**\r
+* array carrying information about the fonts that the system currently knows about\r
+* used to ensure that a font is not loaded twice, among other things\r
+*/\r
+var $fonts=array(); \r
+/**\r
+* a record of the current font\r
+*/\r
+var $currentFont='';\r
+/**\r
+* the current base font\r
+*/\r
+var $currentBaseFont='';\r
+/**\r
+* the number of the current font within the font array\r
+*/\r
+var $currentFontNum=0;\r
+/**\r
+* \r
+*/\r
+var $currentNode;\r
+/**\r
+* object number of the current page\r
+*/\r
+var $currentPage;\r
+/**\r
+* object number of the currently active contents block\r
+*/\r
+var $currentContents;\r
+/**\r
+* number of fonts within the system\r
+*/\r
+var $numFonts=0;\r
+/**\r
+* current colour for fill operations, defaults to inactive value, all three components should be between 0 and 1 inclusive when active\r
+*/\r
+var $currentColour=array('r'=>-1,'g'=>-1,'b'=>-1);\r
+/**\r
+* current colour for stroke operations (lines etc.)\r
+*/\r
+var $currentStrokeColour=array('r'=>-1,'g'=>-1,'b'=>-1);\r
+/**\r
+* current style that lines are drawn in\r
+*/\r
+var $currentLineStyle='';\r
+/**\r
+* an array which is used to save the state of the document, mainly the colours and styles\r
+* it is used to temporarily change to another state, the change back to what it was before\r
+*/\r
+var $stateStack = array();\r
+/**\r
+* number of elements within the state stack\r
+*/\r
+var $nStateStack = 0;\r
+/**\r
+* number of page objects within the document\r
+*/\r
+var $numPages=0;\r
+/**\r
+* object Id storage stack\r
+*/\r
+var $stack=array();\r
+/**\r
+* number of elements within the object Id storage stack\r
+*/\r
+var $nStack=0;\r
+/**\r
+* an array which contains information about the objects which are not firmly attached to pages\r
+* these have been added with the addObject function\r
+*/\r
+var $looseObjects=array();\r
+/**\r
+* array contains infomation about how the loose objects are to be added to the document\r
+*/\r
+var $addLooseObjects=array();\r
+/**\r
+* the objectId of the information object for the document\r
+* this contains authorship, title etc.\r
+*/\r
+var $infoObject=0;\r
+/**\r
+* number of images being tracked within the document\r
+*/\r
+var $numImages=0;\r
+/**\r
+* an array containing options about the document\r
+* it defaults to turning on the compression of the objects\r
+*/\r
+var $options=array('compression'=>1);\r
+/**\r
+* the objectId of the first page of the document\r
+*/\r
+var $firstPageId;\r
+/**\r
+* used to track the last used value of the inter-word spacing, this is so that it is known\r
+* when the spacing is changed.\r
+*/\r
+var $wordSpaceAdjust=0;\r
+/**\r
+* the object Id of the procset object\r
+*/\r
+var $procsetObjectId;\r
+/**\r
+* store the information about the relationship between font families\r
+* this used so that the code knows which font is the bold version of another font, etc.\r
+* the value of this array is initialised in the constuctor function.\r
+*/\r
+var $fontFamilies = array();\r
+/**\r
+* track if the current font is bolded or italicised\r
+*/\r
+var $currentTextState = ''; \r
+/**\r
+* messages are stored here during processing, these can be selected afterwards to give some useful debug information\r
+*/\r
+var $messages='';\r
+/**\r
+* the ancryption array for the document encryption is stored here\r
+*/\r
+var $arc4='';\r
+/**\r
+* the object Id of the encryption information\r
+*/\r
+var $arc4_objnum=0;\r
+/**\r
+* the file identifier, used to uniquely identify a pdf document\r
+*/\r
+var $fileIdentifier='';\r
+/**\r
+* a flag to say if a document is to be encrypted or not\r
+*/\r
+var $encrypted=0;\r
+/**\r
+* the ancryption key for the encryption of all the document content (structure is not encrypted)\r
+*/\r
+var $encryptionKey='';\r
+/**\r
+* array which forms a stack to keep track of nested callback functions\r
+*/\r
+var $callback = array();\r
+/**\r
+* the number of callback functions in the callback array\r
+*/\r
+var $nCallback = 0;\r
+/**\r
+* store label->id pairs for named destinations, these will be used to replace internal links\r
+* done this way so that destinations can be defined after the location that links to them\r
+*/\r
+var $destinations = array();\r
+/**\r
+* store the stack for the transaction commands, each item in here is a record of the values of all the \r
+* variables within the class, so that the user can rollback at will (from each 'start' command)\r
+* note that this includes the objects array, so these can be large.\r
+*/\r
+var $checkpoint = '';\r
+/**\r
+* class constructor\r
+* this will start a new document\r
+* @var array array of 4 numbers, defining the bottom left and upper right corner of the page. first two are normally zero.\r
+*/\r
+function Cpdf ($pageSize=array(0,0,612,792)){\r
+ $this->newDocument($pageSize);\r
+ \r
+ // also initialize the font families that are known about already\r
+ $this->setFontFamily('init');\r
+// $this->fileIdentifier = md5('xxxxxxxx'.time());\r
+\r
+}\r
+\r
+/**\r
+* Document object methods (internal use only)\r
+*\r
+* There is about one object method for each type of object in the pdf document\r
+* Each function has the same call list ($id,$action,$options).\r
+* $id = the object ID of the object, or what it is to be if it is being created\r
+* $action = a string specifying the action to be performed, though ALL must support:\r
+* 'new' - create the object with the id $id\r
+* 'out' - produce the output for the pdf object\r
+* $options = optional, a string or array containing the various parameters for the object\r
+*\r
+* These, in conjunction with the output function are the ONLY way for output to be produced \r
+* within the pdf 'file'.\r
+*/\r
+\r
+/**\r
+*destination object, used to specify the location for the user to jump to, presently on opening\r
+*/\r
+function o_destination($id,$action,$options=''){\r
+ if ($action!='new'){\r
+ $o =& $this->objects[$id];\r
+ }\r
+ switch($action){\r
+ case 'new':\r
+ $this->objects[$id]=array('t'=>'destination','info'=>array());\r
+ $tmp = '';\r
+ switch ($options['type']){\r
+ case 'XYZ':\r
+ case 'FitR':\r
+ $tmp = ' '.$options['p3'].$tmp;\r
+ case 'FitH':\r
+ case 'FitV':\r
+ case 'FitBH':\r
+ case 'FitBV':\r
+ $tmp = ' '.$options['p1'].' '.$options['p2'].$tmp;\r
+ case 'Fit':\r
+ case 'FitB':\r
+ $tmp = $options['type'].$tmp;\r
+ $this->objects[$id]['info']['string']=$tmp;\r
+ $this->objects[$id]['info']['page']=$options['page'];\r
+ }\r
+ break;\r
+ case 'out':\r
+ $tmp = $o['info'];\r
+ $res="\n".$id." 0 obj\n".'['.$tmp['page'].' 0 R /'.$tmp['string']."]\nendobj\n";\r
+ return $res;\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+* set the viewer preferences\r
+*/\r
+function o_viewerPreferences($id,$action,$options=''){\r
+ if ($action!='new'){\r
+ $o =& $this->objects[$id];\r
+ }\r
+ switch ($action){\r
+ case 'new':\r
+ $this->objects[$id]=array('t'=>'viewerPreferences','info'=>array());\r
+ break;\r
+ case 'add':\r
+ foreach($options as $k=>$v){\r
+ switch ($k){\r
+ case 'HideToolbar':\r
+ case 'HideMenubar':\r
+ case 'HideWindowUI':\r
+ case 'FitWindow':\r
+ case 'CenterWindow':\r
+ case 'NonFullScreenPageMode':\r
+ case 'Direction':\r
+ $o['info'][$k]=$v;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ case 'out':\r
+\r
+ $res="\n".$id." 0 obj\n".'<< ';\r
+ foreach($o['info'] as $k=>$v){\r
+ $res.="\n/".$k.' '.$v;\r
+ }\r
+ $res.="\n>>\n";\r
+ return $res;\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+* define the document catalog, the overall controller for the document\r
+*/\r
+function o_catalog($id,$action,$options=''){\r
+ if ($action!='new'){\r
+ $o =& $this->objects[$id];\r
+ }\r
+ switch ($action){\r
+ case 'new':\r
+ $this->objects[$id]=array('t'=>'catalog','info'=>array());\r
+ $this->catalogId=$id;\r
+ break;\r
+ case 'outlines':\r
+ case 'pages':\r
+ case 'openHere':\r
+ $o['info'][$action]=$options;\r
+ break;\r
+ case 'viewerPreferences':\r
+ if (!isset($o['info']['viewerPreferences'])){\r
+ $this->numObj++;\r
+ $this->o_viewerPreferences($this->numObj,'new');\r
+ $o['info']['viewerPreferences']=$this->numObj;\r
+ }\r
+ $vp = $o['info']['viewerPreferences'];\r
+ $this->o_viewerPreferences($vp,'add',$options);\r
+ break;\r
+ case 'out':\r
+ $res="\n".$id." 0 obj\n".'<< /Type /Catalog';\r
+ foreach($o['info'] as $k=>$v){\r
+ switch($k){\r
+ case 'outlines':\r
+ $res.="\n".'/Outlines '.$v.' 0 R';\r
+ break;\r
+ case 'pages':\r
+ $res.="\n".'/Pages '.$v.' 0 R';\r
+ break;\r
+ case 'viewerPreferences':\r
+ $res.="\n".'/ViewerPreferences '.$o['info']['viewerPreferences'].' 0 R';\r
+ break;\r
+ case 'openHere':\r
+ $res.="\n".'/OpenAction '.$o['info']['openHere'].' 0 R';\r
+ break;\r
+ }\r
+ }\r
+ $res.=" >>\nendobj";\r
+ return $res;\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+* object which is a parent to the pages in the document\r
+*/\r
+function o_pages($id,$action,$options=''){\r
+ if ($action!='new'){\r
+ $o =& $this->objects[$id];\r
+ }\r
+ switch ($action){\r
+ case 'new':\r
+ $this->objects[$id]=array('t'=>'pages','info'=>array());\r
+ $this->o_catalog($this->catalogId,'pages',$id);\r
+ break;\r
+ case 'page':\r
+ if (!is_array($options)){\r
+ // then it will just be the id of the new page\r
+ $o['info']['pages'][]=$options;\r
+ } else {\r
+ // then it should be an array having 'id','rid','pos', where rid=the page to which this one will be placed relative\r
+ // and pos is either 'before' or 'after', saying where this page will fit.\r
+ if (isset($options['id']) && isset($options['rid']) && isset($options['pos'])){\r
+ $i = array_search($options['rid'],$o['info']['pages']);\r
+ if (isset($o['info']['pages'][$i]) && $o['info']['pages'][$i]==$options['rid']){\r
+ // then there is a match\r
+ // make a space\r
+ switch ($options['pos']){\r
+ case 'before':\r
+ $k = $i;\r
+ break;\r
+ case 'after':\r
+ $k=$i+1;\r
+ break;\r
+ default:\r
+ $k=-1;\r
+ break;\r
+ }\r
+ if ($k>=0){\r
+ for ($j=count($o['info']['pages'])-1;$j>=$k;$j--){\r
+ $o['info']['pages'][$j+1]=$o['info']['pages'][$j];\r
+ }\r
+ $o['info']['pages'][$k]=$options['id'];\r
+ }\r
+ }\r
+ } \r
+ }\r
+ break;\r
+ case 'procset':\r
+ $o['info']['procset']=$options;\r
+ break;\r
+ case 'mediaBox':\r
+ $o['info']['mediaBox']=$options; // which should be an array of 4 numbers\r
+ break;\r
+ case 'font':\r
+ $o['info']['fonts'][]=array('objNum'=>$options['objNum'],'fontNum'=>$options['fontNum']);\r
+ break;\r
+ case 'xObject':\r
+ $o['info']['xObjects'][]=array('objNum'=>$options['objNum'],'label'=>$options['label']);\r
+ break;\r
+ case 'out':\r
+ if (count($o['info']['pages'])){\r
+ $res="\n".$id." 0 obj\n<< /Type /Pages\n/Kids [";\r
+ foreach($o['info']['pages'] as $k=>$v){\r
+ $res.=$v." 0 R\n";\r
+ }\r
+ $res.="]\n/Count ".count($this->objects[$id]['info']['pages']);\r
+ if ((isset($o['info']['fonts']) && count($o['info']['fonts'])) || isset($o['info']['procset'])){\r
+ $res.="\n/Resources <<";\r
+ if (isset($o['info']['procset'])){\r
+ $res.="\n/ProcSet ".$o['info']['procset']." 0 R";\r
+ }\r
+ if (isset($o['info']['fonts']) && count($o['info']['fonts'])){\r
+ $res.="\n/Font << ";\r
+ foreach($o['info']['fonts'] as $finfo){\r
+ $res.="\n/F".$finfo['fontNum']." ".$finfo['objNum']." 0 R";\r
+ }\r
+ $res.=" >>";\r
+ }\r
+ if (isset($o['info']['xObjects']) && count($o['info']['xObjects'])){\r
+ $res.="\n/XObject << ";\r
+ foreach($o['info']['xObjects'] as $finfo){\r
+ $res.="\n/".$finfo['label']." ".$finfo['objNum']." 0 R";\r
+ }\r
+ $res.=" >>";\r
+ }\r
+ $res.="\n>>";\r
+ if (isset($o['info']['mediaBox'])){\r
+ $tmp=$o['info']['mediaBox'];\r
+ $res.="\n/MediaBox [".sprintf('%.3f',$tmp[0]).' '.sprintf('%.3f',$tmp[1]).' '.sprintf('%.3f',$tmp[2]).' '.sprintf('%.3f',$tmp[3]).']';\r
+ }\r
+ }\r
+ $res.="\n >>\nendobj";\r
+ } else {\r
+ $res="\n".$id." 0 obj\n<< /Type /Pages\n/Count 0\n>>\nendobj";\r
+ }\r
+ return $res;\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+* define the outlines in the doc, empty for now\r
+*/\r
+function o_outlines($id,$action,$options=''){\r
+ if ($action!='new'){\r
+ $o =& $this->objects[$id];\r
+ }\r
+ switch ($action){\r
+ case 'new':\r
+ $this->objects[$id]=array('t'=>'outlines','info'=>array('outlines'=>array()));\r
+ $this->o_catalog($this->catalogId,'outlines',$id);\r
+ break;\r
+ case 'outline':\r
+ $o['info']['outlines'][]=$options;\r
+ break;\r
+ case 'out':\r
+ if (count($o['info']['outlines'])){\r
+ $res="\n".$id." 0 obj\n<< /Type /Outlines /Kids [";\r
+ foreach($o['info']['outlines'] as $k=>$v){\r
+ $res.=$v." 0 R ";\r
+ }\r
+ $res.="] /Count ".count($o['info']['outlines'])." >>\nendobj";\r
+ } else {\r
+ $res="\n".$id." 0 obj\n<< /Type /Outlines /Count 0 >>\nendobj";\r
+ }\r
+ return $res;\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+* an object to hold the font description\r
+*/\r
+function o_font($id,$action,$options=''){\r
+ if ($action!='new'){\r
+ $o =& $this->objects[$id];\r
+ }\r
+ switch ($action){\r
+ case 'new':\r
+ $this->objects[$id]=array('t'=>'font','info'=>array('name'=>$options['name'],'SubType'=>'Type1'));\r
+ $fontNum=$this->numFonts;\r
+ $this->objects[$id]['info']['fontNum']=$fontNum;\r
+ // deal with the encoding and the differences\r
+ if (isset($options['differences'])){\r
+ // then we'll need an encoding dictionary\r
+ $this->numObj++;\r
+ $this->o_fontEncoding($this->numObj,'new',$options);\r
+ $this->objects[$id]['info']['encodingDictionary']=$this->numObj;\r
+ } else if (isset($options['encoding'])){\r
+ // we can specify encoding here\r
+ switch($options['encoding']){\r
+ case 'WinAnsiEncoding':\r
+ case 'MacRomanEncoding':\r
+ case 'MacExpertEncoding':\r
+ $this->objects[$id]['info']['encoding']=$options['encoding'];\r
+ break;\r
+ case 'none':\r
+ break;\r
+ default:\r
+ $this->objects[$id]['info']['encoding']='WinAnsiEncoding';\r
+ break;\r
+ }\r
+ } else {\r
+ $this->objects[$id]['info']['encoding']='WinAnsiEncoding';\r
+ }\r
+ // also tell the pages node about the new font\r
+ $this->o_pages($this->currentNode,'font',array('fontNum'=>$fontNum,'objNum'=>$id));\r
+ break;\r
+ case 'add':\r
+ foreach ($options as $k=>$v){\r
+ switch ($k){\r
+ case 'BaseFont':\r
+ $o['info']['name'] = $v;\r
+ break;\r
+ case 'FirstChar':\r
+ case 'LastChar':\r
+ case 'Widths':\r
+ case 'FontDescriptor':\r
+ case 'SubType':\r
+ $this->addMessage('o_font '.$k." : ".$v);\r
+ $o['info'][$k] = $v;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ case 'out':\r
+ $res="\n".$id." 0 obj\n<< /Type /Font\n/Subtype /".$o['info']['SubType']."\n";\r
+ $res.="/Name /F".$o['info']['fontNum']."\n";\r
+ $res.="/BaseFont /".$o['info']['name']."\n";\r
+ if (isset($o['info']['encodingDictionary'])){\r
+ // then place a reference to the dictionary\r
+ $res.="/Encoding ".$o['info']['encodingDictionary']." 0 R\n";\r
+ } else if (isset($o['info']['encoding'])){\r
+ // use the specified encoding\r
+ $res.="/Encoding /".$o['info']['encoding']."\n";\r
+ }\r
+ if (isset($o['info']['FirstChar'])){\r
+ $res.="/FirstChar ".$o['info']['FirstChar']."\n";\r
+ }\r
+ if (isset($o['info']['LastChar'])){\r
+ $res.="/LastChar ".$o['info']['LastChar']."\n";\r
+ }\r
+ if (isset($o['info']['Widths'])){\r
+ $res.="/Widths ".$o['info']['Widths']." 0 R\n";\r
+ }\r
+ if (isset($o['info']['FontDescriptor'])){\r
+ $res.="/FontDescriptor ".$o['info']['FontDescriptor']." 0 R\n";\r
+ }\r
+ $res.=">>\nendobj";\r
+ return $res;\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+* a font descriptor, needed for including additional fonts\r
+*/\r
+function o_fontDescriptor($id,$action,$options=''){\r
+ if ($action!='new'){\r
+ $o =& $this->objects[$id];\r
+ }\r
+ switch ($action){\r
+ case 'new':\r
+ $this->objects[$id]=array('t'=>'fontDescriptor','info'=>$options);\r
+ break;\r
+ case 'out':\r
+ $res="\n".$id." 0 obj\n<< /Type /FontDescriptor\n";\r
+ foreach ($o['info'] as $label => $value){\r
+ switch ($label){\r
+ case 'Ascent':\r
+ case 'CapHeight':\r
+ case 'Descent':\r
+ case 'Flags':\r
+ case 'ItalicAngle':\r
+ case 'StemV':\r
+ case 'AvgWidth':\r
+ case 'Leading':\r
+ case 'MaxWidth':\r
+ case 'MissingWidth':\r
+ case 'StemH':\r
+ case 'XHeight':\r
+ case 'CharSet':\r
+ if (strlen($value)){\r
+ $res.='/'.$label.' '.$value."\n";\r
+ }\r
+ break;\r
+ case 'FontFile':\r
+ case 'FontFile2':\r
+ case 'FontFile3':\r
+ $res.='/'.$label.' '.$value." 0 R\n";\r
+ break;\r
+ case 'FontBBox':\r
+ $res.='/'.$label.' ['.$value[0].' '.$value[1].' '.$value[2].' '.$value[3]."]\n";\r
+ break;\r
+ case 'FontName':\r
+ $res.='/'.$label.' /'.$value."\n";\r
+ break;\r
+ }\r
+ }\r
+ $res.=">>\nendobj";\r
+ return $res;\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+* the font encoding\r
+*/\r
+function o_fontEncoding($id,$action,$options=''){\r
+ if ($action!='new'){\r
+ $o =& $this->objects[$id];\r
+ }\r
+ switch ($action){\r
+ case 'new':\r
+ // the options array should contain 'differences' and maybe 'encoding'\r
+ $this->objects[$id]=array('t'=>'fontEncoding','info'=>$options);\r
+ break;\r
+ case 'out':\r
+ $res="\n".$id." 0 obj\n<< /Type /Encoding\n";\r
+ if (!isset($o['info']['encoding'])){\r
+ $o['info']['encoding']='WinAnsiEncoding';\r
+ }\r
+ if ($o['info']['encoding']!='none'){\r
+ $res.="/BaseEncoding /".$o['info']['encoding']."\n";\r
+ }\r
+ $res.="/Differences \n[";\r
+ $onum=-100;\r
+ foreach($o['info']['differences'] as $num=>$label){\r
+ if ($num!=$onum+1){\r
+ // we cannot make use of consecutive numbering\r
+ $res.= "\n".$num." /".$label;\r
+ } else {\r
+ $res.= " /".$label;\r
+ }\r
+ $onum=$num;\r
+ }\r
+ $res.="\n]\n>>\nendobj";\r
+ return $res;\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+* the document procset, solves some problems with printing to old PS printers\r
+*/\r
+function o_procset($id,$action,$options=''){\r
+ if ($action!='new'){\r
+ $o =& $this->objects[$id];\r
+ }\r
+ switch ($action){\r
+ case 'new':\r
+ $this->objects[$id]=array('t'=>'procset','info'=>array('PDF'=>1,'Text'=>1));\r
+ $this->o_pages($this->currentNode,'procset',$id);\r
+ $this->procsetObjectId=$id;\r
+ break;\r
+ case 'add':\r
+ // this is to add new items to the procset list, despite the fact that this is considered\r
+ // obselete, the items are required for printing to some postscript printers\r
+ switch ($options) {\r
+ case 'ImageB':\r
+ case 'ImageC':\r
+ case 'ImageI':\r
+ $o['info'][$options]=1;\r
+ break;\r
+ }\r
+ break;\r
+ case 'out':\r
+ $res="\n".$id." 0 obj\n[";\r
+ foreach ($o['info'] as $label=>$val){\r
+ $res.='/'.$label.' ';\r
+ }\r
+ $res.="]\nendobj";\r
+ return $res;\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+* define the document information\r
+*/\r
+function o_info($id,$action,$options=''){\r
+ if ($action!='new'){\r
+ $o =& $this->objects[$id];\r
+ }\r
+ switch ($action){\r
+ case 'new':\r
+ $this->infoObject=$id;\r
+ $date='D:'.date('Ymd');\r
+ $this->objects[$id]=array('t'=>'info','info'=>array('Creator'=>'R and OS php pdf writer, http://www.ros.co.nz','CreationDate'=>$date));\r
+ break;\r
+ case 'Title':\r
+ case 'Author':\r
+ case 'Subject':\r
+ case 'Keywords':\r
+ case 'Creator':\r
+ case 'Producer':\r
+ case 'CreationDate':\r
+ case 'ModDate':\r
+ case 'Trapped':\r
+ $o['info'][$action]=$options;\r
+ break;\r
+ case 'out':\r
+ if ($this->encrypted){\r
+ $this->encryptInit($id);\r
+ }\r
+ $res="\n".$id." 0 obj\n<<\n";\r
+ foreach ($o['info'] as $k=>$v){\r
+ $res.='/'.$k.' (';\r
+ if ($this->encrypted){\r
+ $res.=$this->filterText($this->ARC4($v));\r
+ } else {\r
+ $res.=$this->filterText($v);\r
+ }\r
+ $res.=")\n";\r
+ }\r
+ $res.=">>\nendobj";\r
+ return $res;\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+* an action object, used to link to URLS initially\r
+*/\r
+function o_action($id,$action,$options=''){\r
+ if ($action!='new'){\r
+ $o =& $this->objects[$id];\r
+ }\r
+ switch ($action){\r
+ case 'new':\r
+ if (is_array($options)){\r
+ $this->objects[$id]=array('t'=>'action','info'=>$options,'type'=>$options['type']);\r
+ } else {\r
+ // then assume a URI action\r
+ $this->objects[$id]=array('t'=>'action','info'=>$options,'type'=>'URI');\r
+ }\r
+ break;\r
+ case 'out':\r
+ if ($this->encrypted){\r
+ $this->encryptInit($id);\r
+ }\r
+ $res="\n".$id." 0 obj\n<< /Type /Action";\r
+ switch($o['type']){\r
+ case 'ilink':\r
+ // there will be an 'label' setting, this is the name of the destination\r
+ $res.="\n/S /GoTo\n/D ".$this->destinations[(string)$o['info']['label']]." 0 R";\r
+ break;\r
+ case 'URI':\r
+ $res.="\n/S /URI\n/URI (";\r
+ if ($this->encrypted){\r
+ $res.=$this->filterText($this->ARC4($o['info']));\r
+ } else {\r
+ $res.=$this->filterText($o['info']);\r
+ }\r
+ $res.=")";\r
+ break;\r
+ }\r
+ $res.="\n>>\nendobj";\r
+ return $res;\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+* an annotation object, this will add an annotation to the current page.\r
+* initially will support just link annotations \r
+*/\r
+function o_annotation($id,$action,$options=''){\r
+ if ($action!='new'){\r
+ $o =& $this->objects[$id];\r
+ }\r
+ switch ($action){\r
+ case 'new':\r
+ // add the annotation to the current page\r
+ $pageId = $this->currentPage;\r
+ $this->o_page($pageId,'annot',$id);\r
+ // and add the action object which is going to be required\r
+ switch($options['type']){\r
+ case 'link':\r
+ $this->objects[$id]=array('t'=>'annotation','info'=>$options);\r
+ $this->numObj++;\r
+ $this->o_action($this->numObj,'new',$options['url']);\r
+ $this->objects[$id]['info']['actionId']=$this->numObj;\r
+ break;\r
+ case 'ilink':\r
+ // this is to a named internal link\r
+ $label = $options['label'];\r
+ $this->objects[$id]=array('t'=>'annotation','info'=>$options);\r
+ $this->numObj++;\r
+ $this->o_action($this->numObj,'new',array('type'=>'ilink','label'=>$label));\r
+ $this->objects[$id]['info']['actionId']=$this->numObj;\r
+ break;\r
+ }\r
+ break;\r
+ case 'out':\r
+ $res="\n".$id." 0 obj\n<< /Type /Annot";\r
+ switch($o['info']['type']){\r
+ case 'link':\r
+ case 'ilink':\r
+ $res.= "\n/Subtype /Link";\r
+ break;\r
+ }\r
+ $res.="\n/A ".$o['info']['actionId']." 0 R";\r
+ $res.="\n/Border [0 0 0]";\r
+ $res.="\n/H /I";\r
+ $res.="\n/Rect [ ";\r
+ foreach($o['info']['rect'] as $v){\r
+ $res.= sprintf("%.4f ",$v);\r
+ }\r
+ $res.="]";\r
+ $res.="\n>>\nendobj";\r
+ return $res;\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+* a page object, it also creates a contents object to hold its contents\r
+*/\r
+function o_page($id,$action,$options=''){\r
+ if ($action!='new'){\r
+ $o =& $this->objects[$id];\r
+ }\r
+ switch ($action){\r
+ case 'new':\r
+ $this->numPages++;\r
+ $this->objects[$id]=array('t'=>'page','info'=>array('parent'=>$this->currentNode,'pageNum'=>$this->numPages));\r
+ if (is_array($options)){\r
+ // then this must be a page insertion, array shoudl contain 'rid','pos'=[before|after]\r
+ $options['id']=$id;\r
+ $this->o_pages($this->currentNode,'page',$options);\r
+ } else {\r
+ $this->o_pages($this->currentNode,'page',$id);\r
+ }\r
+ $this->currentPage=$id;\r
+ //make a contents object to go with this page\r
+ $this->numObj++;\r
+ $this->o_contents($this->numObj,'new',$id);\r
+ $this->currentContents=$this->numObj;\r
+ $this->objects[$id]['info']['contents']=array();\r
+ $this->objects[$id]['info']['contents'][]=$this->numObj;\r
+ $match = ($this->numPages%2 ? 'odd' : 'even');\r
+ foreach($this->addLooseObjects as $oId=>$target){\r
+ if ($target=='all' || $match==$target){\r
+ $this->objects[$id]['info']['contents'][]=$oId;\r
+ }\r
+ }\r
+ break;\r
+ case 'content':\r
+ $o['info']['contents'][]=$options;\r
+ break;\r
+ case 'annot':\r
+ // add an annotation to this page\r
+ if (!isset($o['info']['annot'])){\r
+ $o['info']['annot']=array();\r
+ }\r
+ // $options should contain the id of the annotation dictionary\r
+ $o['info']['annot'][]=$options;\r
+ break;\r
+ case 'out':\r
+ $res="\n".$id." 0 obj\n<< /Type /Page";\r
+ $res.="\n/Parent ".$o['info']['parent']." 0 R";\r
+ if (isset($o['info']['annot'])){\r
+ $res.="\n/Annots [";\r
+ foreach($o['info']['annot'] as $aId){\r
+ $res.=" ".$aId." 0 R";\r
+ }\r
+ $res.=" ]";\r
+ }\r
+ $count = count($o['info']['contents']);\r
+ if ($count==1){\r
+ $res.="\n/Contents ".$o['info']['contents'][0]." 0 R";\r
+ } else if ($count>1){\r
+ $res.="\n/Contents [\n";\r
+ foreach ($o['info']['contents'] as $cId){\r
+ $res.=$cId." 0 R\n";\r
+ }\r
+ $res.="]";\r
+ }\r
+ $res.="\n>>\nendobj";\r
+ return $res;\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+* the contents objects hold all of the content which appears on pages\r
+*/\r
+function o_contents($id,$action,$options=''){\r
+ if ($action!='new'){\r
+ $o =& $this->objects[$id];\r
+ }\r
+ switch ($action){\r
+ case 'new':\r
+ $this->objects[$id]=array('t'=>'contents','c'=>'','info'=>array());\r
+ if (strlen($options) && intval($options)){\r
+ // then this contents is the primary for a page\r
+ $this->objects[$id]['onPage']=$options;\r
+ } else if ($options=='raw'){\r
+ // then this page contains some other type of system object\r
+ $this->objects[$id]['raw']=1;\r
+ }\r
+ break;\r
+ case 'add':\r
+ // add more options to the decleration\r
+ foreach ($options as $k=>$v){\r
+ $o['info'][$k]=$v;\r
+ }\r
+ case 'out':\r
+ $tmp=$o['c'];\r
+ $res= "\n".$id." 0 obj\n";\r
+ if (isset($this->objects[$id]['raw'])){\r
+ $res.=$tmp;\r
+ } else {\r
+ $res.= "<<";\r
+ if (function_exists('gzcompress') && $this->options['compression']){\r
+ // then implement ZLIB based compression on this content stream\r
+ $res.=" /Filter /FlateDecode";\r
+ $tmp = gzcompress($tmp);\r
+ }\r
+ if ($this->encrypted){\r
+ $this->encryptInit($id);\r
+ $tmp = $this->ARC4($tmp);\r
+ }\r
+ foreach($o['info'] as $k=>$v){\r
+ $res .= "\n/".$k.' '.$v;\r
+ }\r
+ $res.="\n/Length ".strlen($tmp)." >>\nstream\n".$tmp."\nendstream";\r
+ }\r
+ $res.="\nendobj\n";\r
+ return $res;\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+* an image object, will be an XObject in the document, includes description and data\r
+*/\r
+function o_image($id,$action,$options=''){\r
+ if ($action!='new'){\r
+ $o =& $this->objects[$id];\r
+ }\r
+ switch($action){\r
+ case 'new':\r
+ // make the new object\r
+ $this->objects[$id]=array('t'=>'image','data'=>$options['data'],'info'=>array());\r
+ $this->objects[$id]['info']['Type']='/XObject';\r
+ $this->objects[$id]['info']['Subtype']='/Image';\r
+ $this->objects[$id]['info']['Width']=$options['iw'];\r
+ $this->objects[$id]['info']['Height']=$options['ih'];\r
+ if (!isset($options['type']) || $options['type']=='jpg'){\r
+ if (!isset($options['channels'])){\r
+ $options['channels']=3;\r
+ }\r
+ switch($options['channels']){\r
+ case 1:\r
+ $this->objects[$id]['info']['ColorSpace']='/DeviceGray';\r
+ break;\r
+ default:\r
+ $this->objects[$id]['info']['ColorSpace']='/DeviceRGB';\r
+ break;\r
+ }\r
+ $this->objects[$id]['info']['Filter']='/DCTDecode';\r
+ $this->objects[$id]['info']['BitsPerComponent']=8;\r
+ } else if ($options['type']=='png'){\r
+ $this->objects[$id]['info']['Filter']='/FlateDecode';\r
+ $this->objects[$id]['info']['DecodeParms']='<< /Predictor 15 /Colors '.$options['ncolor'].' /Columns '.$options['iw'].' /BitsPerComponent '.$options['bitsPerComponent'].'>>';\r
+ if (strlen($options['pdata'])){\r
+ $tmp = ' [ /Indexed /DeviceRGB '.(strlen($options['pdata'])/3-1).' ';\r
+ $this->numObj++;\r
+ $this->o_contents($this->numObj,'new');\r
+ $this->objects[$this->numObj]['c']=$options['pdata'];\r
+ $tmp.=$this->numObj.' 0 R';\r
+ $tmp .=' ]';\r
+ $this->objects[$id]['info']['ColorSpace'] = $tmp;\r
+ if (isset($options['transparency'])){\r
+ switch($options['transparency']['type']){\r
+ case 'indexed':\r
+ $tmp=' [ '.$options['transparency']['data'].' '.$options['transparency']['data'].'] ';\r
+ $this->objects[$id]['info']['Mask'] = $tmp;\r
+ break;\r
+ }\r
+ }\r
+ } else {\r
+ $this->objects[$id]['info']['ColorSpace']='/'.$options['color'];\r
+ }\r
+ $this->objects[$id]['info']['BitsPerComponent']=$options['bitsPerComponent'];\r
+ }\r
+ // assign it a place in the named resource dictionary as an external object, according to\r
+ // the label passed in with it.\r
+ $this->o_pages($this->currentNode,'xObject',array('label'=>$options['label'],'objNum'=>$id));\r
+ // also make sure that we have the right procset object for it.\r
+ $this->o_procset($this->procsetObjectId,'add','ImageC');\r
+ break;\r
+ case 'out':\r
+ $tmp=$o['data'];\r
+ $res= "\n".$id." 0 obj\n<<";\r
+ foreach($o['info'] as $k=>$v){\r
+ $res.="\n/".$k.' '.$v;\r
+ }\r
+ if ($this->encrypted){\r
+ $this->encryptInit($id);\r
+ $tmp = $this->ARC4($tmp);\r
+ }\r
+ $res.="\n/Length ".strlen($tmp)." >>\nstream\n".$tmp."\nendstream\nendobj\n";\r
+ return $res;\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+* encryption object.\r
+*/\r
+function o_encryption($id,$action,$options=''){\r
+ if ($action!='new'){\r
+ $o =& $this->objects[$id];\r
+ }\r
+ switch($action){\r
+ case 'new':\r
+ // make the new object\r
+ $this->objects[$id]=array('t'=>'encryption','info'=>$options);\r
+ $this->arc4_objnum=$id;\r
+ // figure out the additional paramaters required\r
+ $pad = chr(0x28).chr(0xBF).chr(0x4E).chr(0x5E).chr(0x4E).chr(0x75).chr(0x8A).chr(0x41).chr(0x64).chr(0x00).chr(0x4E).chr(0x56).chr(0xFF).chr(0xFA).chr(0x01).chr(0x08).chr(0x2E).chr(0x2E).chr(0x00).chr(0xB6).chr(0xD0).chr(0x68).chr(0x3E).chr(0x80).chr(0x2F).chr(0x0C).chr(0xA9).chr(0xFE).chr(0x64).chr(0x53).chr(0x69).chr(0x7A);\r
+ $len = strlen($options['owner']);\r
+ if ($len>32){\r
+ $owner = substr($options['owner'],0,32);\r
+ } else if ($len<32){\r
+ $owner = $options['owner'].substr($pad,0,32-$len);\r
+ } else {\r
+ $owner = $options['owner'];\r
+ }\r
+ $len = strlen($options['user']);\r
+ if ($len>32){\r
+ $user = substr($options['user'],0,32);\r
+ } else if ($len<32){\r
+ $user = $options['user'].substr($pad,0,32-$len);\r
+ } else {\r
+ $user = $options['user'];\r
+ }\r
+ $tmp = $this->md5_16($owner);\r
+ $okey = substr($tmp,0,5);\r
+ $this->ARC4_init($okey);\r
+ $ovalue=$this->ARC4($user);\r
+ $this->objects[$id]['info']['O']=$ovalue;\r
+ // now make the u value, phew.\r
+ $tmp = $this->md5_16($user.$ovalue.chr($options['p']).chr(255).chr(255).chr(255).$this->fileIdentifier);\r
+ $ukey = substr($tmp,0,5);\r
+\r
+ $this->ARC4_init($ukey);\r
+ $this->encryptionKey = $ukey;\r
+ $this->encrypted=1;\r
+ $uvalue=$this->ARC4($pad);\r
+\r
+ $this->objects[$id]['info']['U']=$uvalue;\r
+ $this->encryptionKey=$ukey;\r
+ \r
+ // initialize the arc4 array\r
+ break;\r
+ case 'out':\r
+ $res= "\n".$id." 0 obj\n<<";\r
+ $res.="\n/Filter /Standard";\r
+ $res.="\n/V 1";\r
+ $res.="\n/R 2";\r
+ $res.="\n/O (".$this->filterText($o['info']['O']).')';\r
+ $res.="\n/U (".$this->filterText($o['info']['U']).')';\r
+ // and the p-value needs to be converted to account for the twos-complement approach\r
+ $o['info']['p'] = (($o['info']['p']^255)+1)*-1;\r
+ $res.="\n/P ".($o['info']['p']);\r
+ $res.="\n>>\nendobj\n";\r
+ \r
+ return $res;\r
+ break;\r
+ }\r
+}\r
+ \r
+/**\r
+* ARC4 functions\r
+* A series of function to implement ARC4 encoding in PHP\r
+*/\r
+\r
+/**\r
+* calculate the 16 byte version of the 128 bit md5 digest of the string\r
+*/\r
+function md5_16($string){\r
+ $tmp = md5($string);\r
+ $out='';\r
+ for ($i=0;$i<=30;$i=$i+2){\r
+ $out.=chr(hexdec(substr($tmp,$i,2)));\r
+ }\r
+ return $out;\r
+}\r
+\r
+/**\r
+* initialize the encryption for processing a particular object \r
+*/\r
+function encryptInit($id){\r
+ $tmp = $this->encryptionKey;\r
+ $hex = dechex($id);\r
+ if (strlen($hex)<6){\r
+ $hex = substr('000000',0,6-strlen($hex)).$hex;\r
+ }\r
+ $tmp.= chr(hexdec(substr($hex,4,2))).chr(hexdec(substr($hex,2,2))).chr(hexdec(substr($hex,0,2))).chr(0).chr(0);\r
+ $key = $this->md5_16($tmp);\r
+ $this->ARC4_init(substr($key,0,10));\r
+}\r
+\r
+/**\r
+* initialize the ARC4 encryption\r
+*/\r
+function ARC4_init($key=''){\r
+ $this->arc4 = '';\r
+ // setup the control array\r
+ if (strlen($key)==0){\r
+ return;\r
+ }\r
+ $k = '';\r
+ while(strlen($k)<256){\r
+ $k.=$key;\r
+ }\r
+ $k=substr($k,0,256);\r
+ for ($i=0;$i<256;$i++){\r
+ $this->arc4 .= chr($i);\r
+ }\r
+ $j=0;\r
+ for ($i=0;$i<256;$i++){\r
+ $t = $this->arc4[$i];\r
+ $j = ($j + ord($t) + ord($k[$i]))%256;\r
+ $this->arc4[$i]=$this->arc4[$j];\r
+ $this->arc4[$j]=$t;\r
+ } \r
+}\r
+\r
+/**\r
+* ARC4 encrypt a text string\r
+*/\r
+function ARC4($text){\r
+ $len=strlen($text);\r
+ $a=0;\r
+ $b=0;\r
+ $c = $this->arc4;\r
+ $out='';\r
+ for ($i=0;$i<$len;$i++){\r
+ $a = ($a+1)%256;\r
+ $t= $c[$a];\r
+ $b = ($b+ord($t))%256;\r
+ $c[$a]=$c[$b];\r
+ $c[$b]=$t;\r
+ $k = ord($c[(ord($c[$a])+ord($c[$b]))%256]);\r
+ $out.=chr(ord($text[$i]) ^ $k);\r
+ }\r
+ \r
+ return $out;\r
+}\r
+\r
+/**\r
+* functions which can be called to adjust or add to the document\r
+*/\r
+\r
+/**\r
+* add a link in the document to an external URL\r
+*/\r
+function addLink($url,$x0,$y0,$x1,$y1){\r
+ $this->numObj++;\r
+ $info = array('type'=>'link','url'=>$url,'rect'=>array($x0,$y0,$x1,$y1));\r
+ $this->o_annotation($this->numObj,'new',$info);\r
+}\r
+\r
+/**\r
+* add a link in the document to an internal destination (ie. within the document)\r
+*/\r
+function addInternalLink($label,$x0,$y0,$x1,$y1){\r
+ $this->numObj++;\r
+ $info = array('type'=>'ilink','label'=>$label,'rect'=>array($x0,$y0,$x1,$y1));\r
+ $this->o_annotation($this->numObj,'new',$info);\r
+}\r
+\r
+/**\r
+* set the encryption of the document\r
+* can be used to turn it on and/or set the passwords which it will have.\r
+* also the functions that the user will have are set here, such as print, modify, add\r
+*/\r
+function setEncryption($userPass='',$ownerPass='',$pc=array()){\r
+ $p=bindec(11000000);\r
+\r
+ $options = array(\r
+ 'print'=>4\r
+ ,'modify'=>8\r
+ ,'copy'=>16\r
+ ,'add'=>32\r
+ );\r
+ foreach($pc as $k=>$v){\r
+ if ($v && isset($options[$k])){\r
+ $p+=$options[$k];\r
+ } else if (isset($options[$v])){\r
+ $p+=$options[$v];\r
+ }\r
+ }\r
+ // implement encryption on the document\r
+ if ($this->arc4_objnum == 0){\r
+ // then the block does not exist already, add it.\r
+ $this->numObj++;\r
+ if (strlen($ownerPass)==0){\r
+ $ownerPass=$userPass;\r
+ }\r
+ $this->o_encryption($this->numObj,'new',array('user'=>$userPass,'owner'=>$ownerPass,'p'=>$p));\r
+ }\r
+}\r
+\r
+/**\r
+* should be used for internal checks, not implemented as yet\r
+*/\r
+function checkAllHere(){\r
+}\r
+\r
+/**\r
+* return the pdf stream as a string returned from the function\r
+*/\r
+function output($debug=0){\r
+\r
+ if ($debug){\r
+ // turn compression off\r
+ $this->options['compression']=0;\r
+ }\r
+\r
+ if ($this->arc4_objnum){\r
+ $this->ARC4_init($this->encryptionKey);\r
+ }\r
+\r
+ $this->checkAllHere();\r
+\r
+ $xref=array();\r
+ $content="%PDF-1.3\n%âãÏÓ\n";\r
+// $content="%PDF-1.3\n";\r
+ $pos=strlen($content);\r
+ foreach($this->objects as $k=>$v){\r
+ $tmp='o_'.$v['t'];\r
+ $cont=$this->$tmp($k,'out');\r
+ $content.=$cont;\r
+ $xref[]=$pos;\r
+ $pos+=strlen($cont);\r
+ }\r
+ $content.="\nxref\n0 ".(count($xref)+1)."\n0000000000 65535 f \n";\r
+ foreach($xref as $p){\r
+ $content.=substr('0000000000',0,10-strlen($p)).$p." 00000 n \n";\r
+ }\r
+ $content.="\ntrailer\n << /Size ".(count($xref)+1)."\n /Root 1 0 R\n /Info ".$this->infoObject." 0 R\n";\r
+ // if encryption has been applied to this document then add the marker for this dictionary\r
+ if ($this->arc4_objnum > 0){\r
+ $content .= "/Encrypt ".$this->arc4_objnum." 0 R\n";\r
+ }\r
+ if (strlen($this->fileIdentifier)){\r
+ $content .= "/ID[<".$this->fileIdentifier."><".$this->fileIdentifier.">]\n";\r
+ }\r
+ $content .= " >>\nstartxref\n".$pos."\n%%EOF\n";\r
+ return $content;\r
+}\r
+\r
+/**\r
+* intialize a new document\r
+* if this is called on an existing document results may be unpredictable, but the existing document would be lost at minimum\r
+* this function is called automatically by the constructor function\r
+*\r
+* @access private\r
+*/\r
+function newDocument($pageSize=array(0,0,612,792)){\r
+ $this->numObj=0;\r
+ $this->objects = array();\r
+\r
+ $this->numObj++;\r
+ $this->o_catalog($this->numObj,'new');\r
+\r
+ $this->numObj++;\r
+ $this->o_outlines($this->numObj,'new');\r
+\r
+ $this->numObj++;\r
+ $this->o_pages($this->numObj,'new');\r
+\r
+ $this->o_pages($this->numObj,'mediaBox',$pageSize);\r
+ $this->currentNode = 3;\r
+\r
+ $this->numObj++;\r
+ $this->o_procset($this->numObj,'new');\r
+\r
+ $this->numObj++;\r
+ $this->o_info($this->numObj,'new');\r
+\r
+ $this->numObj++;\r
+ $this->o_page($this->numObj,'new');\r
+\r
+ // need to store the first page id as there is no way to get it to the user during \r
+ // startup\r
+ $this->firstPageId = $this->currentContents;\r
+}\r
+\r
+/**\r
+* open the font file and return a php structure containing it.\r
+* first check if this one has been done before and saved in a form more suited to php\r
+* note that if a php serialized version does not exist it will try and make one, but will\r
+* require write access to the directory to do it... it is MUCH faster to have these serialized\r
+* files.\r
+*\r
+* @access private\r
+*/\r
+function openFont($font){\r
+ // assume that $font contains both the path and perhaps the extension to the file, split them\r
+ $pos=strrpos($font,'/');\r
+ if ($pos===false){\r
+ $dir = './';\r
+ $name = $font;\r
+ } else {\r
+ $dir=substr($font,0,$pos+1);\r
+ $name=substr($font,$pos+1);\r
+ }\r
+\r
+ if (substr($name,-4)=='.afm'){\r
+ $name=substr($name,0,strlen($name)-4);\r
+ }\r
+ $this->addMessage('openFont: '.$font.' - '.$name);\r
+ if (file_exists($dir.'php_'.$name.'.afm')){\r
+ $this->addMessage('openFont: php file exists '.$dir.'php_'.$name.'.afm');\r
+ $tmp = file($dir.'php_'.$name.'.afm');\r
+ $this->fonts[$font]=unserialize($tmp[0]);\r
+ if (!isset($this->fonts[$font]['_version_']) || $this->fonts[$font]['_version_']<1){\r
+ // if the font file is old, then clear it out and prepare for re-creation\r
+ $this->addMessage('openFont: clear out, make way for new version.');\r
+ unset($this->fonts[$font]);\r
+ }\r
+ }\r
+ if (!isset($this->fonts[$font]) && file_exists($dir.$name.'.afm')){\r
+ // then rebuild the php_<font>.afm file from the <font>.afm file\r
+ $this->addMessage('openFont: build php file from '.$dir.$name.'.afm');\r
+ $data = array();\r
+ $file = file($dir.$name.'.afm');\r
+ foreach ($file as $rowA){\r
+ $row=trim($rowA);\r
+ $pos=strpos($row,' ');\r
+ if ($pos){\r
+ // then there must be some keyword\r
+ $key = substr($row,0,$pos);\r
+ switch ($key){\r
+ case 'FontName':\r
+ case 'FullName':\r
+ case 'FamilyName':\r
+ case 'Weight':\r
+ case 'ItalicAngle':\r
+ case 'IsFixedPitch':\r
+ case 'CharacterSet':\r
+ case 'UnderlinePosition':\r
+ case 'UnderlineThickness':\r
+ case 'Version':\r
+ case 'EncodingScheme':\r
+ case 'CapHeight':\r
+ case 'XHeight':\r
+ case 'Ascender':\r
+ case 'Descender':\r
+ case 'StdHW':\r
+ case 'StdVW':\r
+ case 'StartCharMetrics':\r
+ $data[$key]=trim(substr($row,$pos));\r
+ break;\r
+ case 'FontBBox':\r
+ $data[$key]=explode(' ',trim(substr($row,$pos)));\r
+ break;\r
+ case 'C':\r
+ //C 39 ; WX 222 ; N quoteright ; B 53 463 157 718 ;\r
+ $bits=explode(';',trim($row));\r
+ $dtmp=array();\r
+ foreach($bits as $bit){\r
+ $bits2 = explode(' ',trim($bit));\r
+ if (strlen($bits2[0])){\r
+ if (count($bits2)>2){\r
+ $dtmp[$bits2[0]]=array();\r
+ for ($i=1;$i<count($bits2);$i++){\r
+ $dtmp[$bits2[0]][]=$bits2[$i];\r
+ }\r
+ } else if (count($bits2)==2){\r
+ $dtmp[$bits2[0]]=$bits2[1];\r
+ }\r
+ }\r
+ }\r
+ if ($dtmp['C']>=0){\r
+ $data['C'][$dtmp['C']]=$dtmp;\r
+ $data['C'][$dtmp['N']]=$dtmp;\r
+ } else {\r
+ $data['C'][$dtmp['N']]=$dtmp;\r
+ }\r
+ break;\r
+ case 'KPX':\r
+ //KPX Adieresis yacute -40\r
+ $bits=explode(' ',trim($row));\r
+ $data['KPX'][$bits[1]][$bits[2]]=$bits[3];\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ $data['_version_']=1;\r
+ $this->fonts[$font]=$data;\r
+ $fp = fopen($dir.'php_'.$name.'.afm','w');\r
+ fwrite($fp,serialize($data));\r
+ fclose($fp);\r
+ } else if (!isset($this->fonts[$font])){\r
+ $this->addMessage('openFont: no font file found');\r
+// echo 'Font not Found '.$font;\r
+ }\r
+}\r
+\r
+/**\r
+* if the font is not loaded then load it and make the required object\r
+* else just make it the current font\r
+* the encoding array can contain 'encoding'=> 'none','WinAnsiEncoding','MacRomanEncoding' or 'MacExpertEncoding'\r
+* note that encoding='none' will need to be used for symbolic fonts\r
+* and 'differences' => an array of mappings between numbers 0->255 and character names.\r
+*\r
+*/\r
+function selectFont($fontName,$encoding='',$set=1){\r
+ if (!isset($this->fonts[$fontName])){\r
+ // load the file\r
+ $this->openFont($fontName);\r
+ if (isset($this->fonts[$fontName])){\r
+ $this->numObj++;\r
+ $this->numFonts++;\r
+ $pos=strrpos($fontName,'/');\r
+// $dir=substr($fontName,0,$pos+1);\r
+ $name=substr($fontName,$pos+1);\r
+ if (substr($name,-4)=='.afm'){\r
+ $name=substr($name,0,strlen($name)-4);\r
+ }\r
+ $options=array('name'=>$name);\r
+ if (is_array($encoding)){\r
+ // then encoding and differences might be set\r
+ if (isset($encoding['encoding'])){\r
+ $options['encoding']=$encoding['encoding'];\r
+ }\r
+ if (isset($encoding['differences'])){\r
+ $options['differences']=$encoding['differences'];\r
+ }\r
+ } else if (strlen($encoding)){\r
+ // then perhaps only the encoding has been set\r
+ $options['encoding']=$encoding;\r
+ }\r
+ $fontObj = $this->numObj;\r
+ $this->o_font($this->numObj,'new',$options);\r
+ $this->fonts[$fontName]['fontNum']=$this->numFonts;\r
+ // if this is a '.afm' font, and there is a '.pfa' file to go with it ( as there\r
+ // should be for all non-basic fonts), then load it into an object and put the\r
+ // references into the font object\r
+ $basefile = substr($fontName,0,strlen($fontName)-4);\r
+ if (file_exists($basefile.'.pfb')){\r
+ $fbtype = 'pfb';\r
+ } else if (file_exists($basefile.'.ttf')){\r
+ $fbtype = 'ttf';\r
+ } else {\r
+ $fbtype='';\r
+ }\r
+ $fbfile = $basefile.'.'.$fbtype;\r
+ \r
+// $pfbfile = substr($fontName,0,strlen($fontName)-4).'.pfb';\r
+// $ttffile = substr($fontName,0,strlen($fontName)-4).'.ttf';\r
+ $this->addMessage('selectFont: checking for - '.$fbfile);\r
+ if (substr($fontName,-4)=='.afm' && strlen($fbtype) ){\r
+ $adobeFontName = $this->fonts[$fontName]['FontName'];\r
+// $fontObj = $this->numObj;\r
+ $this->addMessage('selectFont: adding font file - '.$fbfile.' - '.$adobeFontName);\r
+ // find the array of fond widths, and put that into an object.\r
+ $firstChar = -1;\r
+ $lastChar = 0;\r
+ $widths = array();\r
+ foreach ($this->fonts[$fontName]['C'] as $num=>$d){\r
+ if (intval($num)>0 || $num=='0'){\r
+ if ($lastChar>0 && $num>$lastChar+1){\r
+ for($i=$lastChar+1;$i<$num;$i++){\r
+ $widths[] = 0;\r
+ }\r
+ }\r
+ $widths[] = $d['WX'];\r
+ if ($firstChar==-1){\r
+ $firstChar = $num;\r
+ }\r
+ $lastChar = $num;\r
+ }\r
+ }\r
+ // also need to adjust the widths for the differences array\r
+ if (isset($options['differences'])){\r
+ foreach($options['differences'] as $charNum=>$charName){\r
+ if ($charNum>$lastChar){\r
+ for($i=$lastChar+1;$i<=$charNum;$i++){\r
+ $widths[]=0;\r
+ }\r
+ $lastChar=$charNum;\r
+ }\r
+ if (isset($this->fonts[$fontName]['C'][$charName])){\r
+ $widths[$charNum-$firstChar]=$this->fonts[$fontName]['C'][$charName]['WX'];\r
+ }\r
+ }\r
+ }\r
+ $this->addMessage('selectFont: FirstChar='.$firstChar);\r
+ $this->addMessage('selectFont: LastChar='.$lastChar);\r
+ $this->numObj++;\r
+ $this->o_contents($this->numObj,'new','raw');\r
+ $this->objects[$this->numObj]['c'].='[';\r
+ foreach($widths as $width){\r
+ $this->objects[$this->numObj]['c'].=' '.$width;\r
+ }\r
+ $this->objects[$this->numObj]['c'].=' ]';\r
+ $widthid = $this->numObj;\r
+\r
+ // load the pfb file, and put that into an object too.\r
+ // note that pdf supports only binary format type 1 font files, though there is a \r
+ // simple utility to convert them from pfa to pfb.\r
+ $fp = fopen($fbfile,'rb');\r
+ $tmp = get_magic_quotes_runtime();\r
+ set_magic_quotes_runtime(0);\r
+ $data = fread($fp,filesize($fbfile));\r
+ set_magic_quotes_runtime($tmp);\r
+ fclose($fp);\r
+\r
+ // create the font descriptor\r
+ $this->numObj++;\r
+ $fontDescriptorId = $this->numObj;\r
+ $this->numObj++;\r
+ $pfbid = $this->numObj;\r
+ // determine flags (more than a little flakey, hopefully will not matter much)\r
+ $flags=0;\r
+ if ($this->fonts[$fontName]['ItalicAngle']!=0){ $flags+=pow(2,6); }\r
+ if ($this->fonts[$fontName]['IsFixedPitch']=='true'){ $flags+=1; }\r
+ $flags+=pow(2,5); // assume non-sybolic\r
+\r
+ $list = array('Ascent'=>'Ascender','CapHeight'=>'CapHeight','Descent'=>'Descender','FontBBox'=>'FontBBox','ItalicAngle'=>'ItalicAngle');\r
+ $fdopt = array(\r
+ 'Flags'=>$flags\r
+ ,'FontName'=>$adobeFontName\r
+ ,'StemV'=>100 // don't know what the value for this should be!\r
+ );\r
+ foreach($list as $k=>$v){\r
+ if (isset($this->fonts[$fontName][$v])){\r
+ $fdopt[$k]=$this->fonts[$fontName][$v];\r
+ }\r
+ }\r
+\r
+ if ($fbtype=='pfb'){\r
+ $fdopt['FontFile']=$pfbid;\r
+ } else if ($fbtype=='ttf'){\r
+ $fdopt['FontFile2']=$pfbid;\r
+ }\r
+ $this->o_fontDescriptor($fontDescriptorId,'new',$fdopt); \r
+\r
+ // embed the font program\r
+ $this->o_contents($this->numObj,'new');\r
+ $this->objects[$pfbid]['c'].=$data;\r
+ // determine the cruicial lengths within this file\r
+ if ($fbtype=='pfb'){\r
+ $l1 = strpos($data,'eexec')+6;\r
+ $l2 = strpos($data,'00000000')-$l1;\r
+ $l3 = strlen($data)-$l2-$l1;\r
+ $this->o_contents($this->numObj,'add',array('Length1'=>$l1,'Length2'=>$l2,'Length3'=>$l3));\r
+ } else if ($fbtype=='ttf'){\r
+ $l1 = strlen($data);\r
+ $this->o_contents($this->numObj,'add',array('Length1'=>$l1));\r
+ }\r
+\r
+\r
+ // tell the font object about all this new stuff\r
+ $tmp = array('BaseFont'=>$adobeFontName,'Widths'=>$widthid\r
+ ,'FirstChar'=>$firstChar,'LastChar'=>$lastChar\r
+ ,'FontDescriptor'=>$fontDescriptorId);\r
+ if ($fbtype=='ttf'){\r
+ $tmp['SubType']='TrueType';\r
+ }\r
+ $this->addMessage('adding extra info to font.('.$fontObj.')');\r
+ foreach($tmp as $fk=>$fv){\r
+ $this->addMessage($fk." : ".$fv);\r
+ }\r
+ $this->o_font($fontObj,'add',$tmp);\r
+\r
+ } else {\r
+ $this->addMessage('selectFont: pfb or ttf file not found, ok if this is one of the 14 standard fonts');\r
+ }\r
+\r
+\r
+ // also set the differences here, note that this means that these will take effect only the \r
+ //first time that a font is selected, else they are ignored\r
+ if (isset($options['differences'])){\r
+ $this->fonts[$fontName]['differences']=$options['differences'];\r
+ }\r
+ }\r
+ }\r
+ if ($set && isset($this->fonts[$fontName])){\r
+ // so if for some reason the font was not set in the last one then it will not be selected\r
+ $this->currentBaseFont=$fontName;\r
+ // the next line means that if a new font is selected, then the current text state will be\r
+ // applied to it as well.\r
+ $this->setCurrentFont();\r
+ }\r
+ return $this->currentFontNum;\r
+}\r
+\r
+/**\r
+* sets up the current font, based on the font families, and the current text state\r
+* note that this system is quite flexible, a <b><i> font can be completely different to a\r
+* <i><b> font, and even <b><b> will have to be defined within the family to have meaning\r
+* This function is to be called whenever the currentTextState is changed, it will update\r
+* the currentFont setting to whatever the appropriatte family one is.\r
+* If the user calls selectFont themselves then that will reset the currentBaseFont, and the currentFont\r
+* This function will change the currentFont to whatever it should be, but will not change the \r
+* currentBaseFont.\r
+*\r
+* @access private\r
+*/\r
+function setCurrentFont(){\r
+ if (strlen($this->currentBaseFont)==0){\r
+ // then assume an initial font\r
+ $this->selectFont('./fonts/Helvetica.afm');\r
+ }\r
+ $cf = substr($this->currentBaseFont,strrpos($this->currentBaseFont,'/')+1);\r
+ if (strlen($this->currentTextState)\r
+ && isset($this->fontFamilies[$cf]) \r
+ && isset($this->fontFamilies[$cf][$this->currentTextState])){\r
+ // then we are in some state or another\r
+ // and this font has a family, and the current setting exists within it\r
+ // select the font, then return it\r
+ $nf = substr($this->currentBaseFont,0,strrpos($this->currentBaseFont,'/')+1).$this->fontFamilies[$cf][$this->currentTextState];\r
+ $this->selectFont($nf,'',0);\r
+ $this->currentFont = $nf;\r
+ $this->currentFontNum = $this->fonts[$nf]['fontNum'];\r
+ } else {\r
+ // the this font must not have the right family member for the current state\r
+ // simply assume the base font\r
+ $this->currentFont = $this->currentBaseFont;\r
+ $this->currentFontNum = $this->fonts[$this->currentFont]['fontNum']; \r
+ }\r
+}\r
+\r
+/**\r
+* function for the user to find out what the ID is of the first page that was created during\r
+* startup - useful if they wish to add something to it later.\r
+*/\r
+function getFirstPageId(){\r
+ return $this->firstPageId;\r
+}\r
+\r
+/**\r
+* add content to the currently active object\r
+*\r
+* @access private\r
+*/\r
+function addContent($content){\r
+ $this->objects[$this->currentContents]['c'].=$content;\r
+}\r
+\r
+/**\r
+* sets the colour for fill operations\r
+*/\r
+function setColor($r,$g,$b,$force=0){\r
+ if ($r>=0 && ($force || $r!=$this->currentColour['r'] || $g!=$this->currentColour['g'] || $b!=$this->currentColour['b'])){\r
+ $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$r).' '.sprintf('%.3f',$g).' '.sprintf('%.3f',$b).' rg';\r
+ $this->currentColour=array('r'=>$r,'g'=>$g,'b'=>$b);\r
+ }\r
+}\r
+\r
+/**\r
+* sets the colour for stroke operations\r
+*/\r
+function setStrokeColor($r,$g,$b,$force=0){\r
+ if ($r>=0 && ($force || $r!=$this->currentStrokeColour['r'] || $g!=$this->currentStrokeColour['g'] || $b!=$this->currentStrokeColour['b'])){\r
+ $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$r).' '.sprintf('%.3f',$g).' '.sprintf('%.3f',$b).' RG';\r
+ $this->currentStrokeColour=array('r'=>$r,'g'=>$g,'b'=>$b);\r
+ }\r
+}\r
+\r
+/**\r
+* draw a line from one set of coordinates to another\r
+*/\r
+function line($x1,$y1,$x2,$y2){\r
+ $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$x1).' '.sprintf('%.3f',$y1).' m '.sprintf('%.3f',$x2).' '.sprintf('%.3f',$y2).' l S';\r
+}\r
+\r
+/**\r
+* draw a bezier curve based on 4 control points\r
+*/\r
+function curve($x0,$y0,$x1,$y1,$x2,$y2,$x3,$y3){\r
+ // in the current line style, draw a bezier curve from (x0,y0) to (x3,y3) using the other two points\r
+ // as the control points for the curve.\r
+ $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$x0).' '.sprintf('%.3f',$y0).' m '.sprintf('%.3f',$x1).' '.sprintf('%.3f',$y1);\r
+ $this->objects[$this->currentContents]['c'].= ' '.sprintf('%.3f',$x2).' '.sprintf('%.3f',$y2).' '.sprintf('%.3f',$x3).' '.sprintf('%.3f',$y3).' c S';\r
+}\r
+\r
+/**\r
+* draw a part of an ellipse\r
+*/\r
+function partEllipse($x0,$y0,$astart,$afinish,$r1,$r2=0,$angle=0,$nSeg=8){\r
+ $this->ellipse($x0,$y0,$r1,$r2,$angle,$nSeg,$astart,$afinish,0);\r
+}\r
+\r
+/**\r
+* draw a filled ellipse\r
+*/\r
+function filledEllipse($x0,$y0,$r1,$r2=0,$angle=0,$nSeg=8,$astart=0,$afinish=360){\r
+ return $this->ellipse($x0,$y0,$r1,$r2=0,$angle,$nSeg,$astart,$afinish,1,1);\r
+}\r
+\r
+/**\r
+* draw an ellipse\r
+* note that the part and filled ellipse are just special cases of this function\r
+*\r
+* draws an ellipse in the current line style\r
+* centered at $x0,$y0, radii $r1,$r2\r
+* if $r2 is not set, then a circle is drawn\r
+* nSeg is not allowed to be less than 2, as this will simply draw a line (and will even draw a \r
+* pretty crappy shape at 2, as we are approximating with bezier curves.\r
+*/\r
+function ellipse($x0,$y0,$r1,$r2=0,$angle=0,$nSeg=8,$astart=0,$afinish=360,$close=1,$fill=0){\r
+ if ($r1==0){\r
+ return;\r
+ }\r
+ if ($r2==0){\r
+ $r2=$r1;\r
+ }\r
+ if ($nSeg<2){\r
+ $nSeg=2;\r
+ }\r
+\r
+ $astart = deg2rad((float)$astart);\r
+ $afinish = deg2rad((float)$afinish);\r
+ $totalAngle =$afinish-$astart;\r
+\r
+ $dt = $totalAngle/$nSeg;\r
+ $dtm = $dt/3;\r
+\r
+ if ($angle != 0){\r
+ $a = -1*deg2rad((float)$angle);\r
+ $tmp = "\n q ";\r
+ $tmp .= sprintf('%.3f',cos($a)).' '.sprintf('%.3f',(-1.0*sin($a))).' '.sprintf('%.3f',sin($a)).' '.sprintf('%.3f',cos($a)).' ';\r
+ $tmp .= sprintf('%.3f',$x0).' '.sprintf('%.3f',$y0).' cm';\r
+ $this->objects[$this->currentContents]['c'].= $tmp;\r
+ $x0=0;\r
+ $y0=0;\r
+ }\r
+\r
+ $t1 = $astart;\r
+ $a0 = $x0+$r1*cos($t1);\r
+ $b0 = $y0+$r2*sin($t1);\r
+ $c0 = -$r1*sin($t1);\r
+ $d0 = $r2*cos($t1);\r
+\r
+ $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$a0).' '.sprintf('%.3f',$b0).' m ';\r
+ for ($i=1;$i<=$nSeg;$i++){\r
+ // draw this bit of the total curve\r
+ $t1 = $i*$dt+$astart;\r
+ $a1 = $x0+$r1*cos($t1);\r
+ $b1 = $y0+$r2*sin($t1);\r
+ $c1 = -$r1*sin($t1);\r
+ $d1 = $r2*cos($t1);\r
+ $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',($a0+$c0*$dtm)).' '.sprintf('%.3f',($b0+$d0*$dtm));\r
+ $this->objects[$this->currentContents]['c'].= ' '.sprintf('%.3f',($a1-$c1*$dtm)).' '.sprintf('%.3f',($b1-$d1*$dtm)).' '.sprintf('%.3f',$a1).' '.sprintf('%.3f',$b1).' c';\r
+ $a0=$a1;\r
+ $b0=$b1;\r
+ $c0=$c1;\r
+ $d0=$d1; \r
+ }\r
+ if ($fill){\r
+ $this->objects[$this->currentContents]['c'].=' f';\r
+ } else {\r
+ if ($close){\r
+ $this->objects[$this->currentContents]['c'].=' s'; // small 's' signifies closing the path as well\r
+ } else {\r
+ $this->objects[$this->currentContents]['c'].=' S';\r
+ }\r
+ }\r
+ if ($angle !=0){\r
+ $this->objects[$this->currentContents]['c'].=' Q';\r
+ }\r
+}\r
+\r
+/**\r
+* this sets the line drawing style.\r
+* width, is the thickness of the line in user units\r
+* cap is the type of cap to put on the line, values can be 'butt','round','square'\r
+* where the diffference between 'square' and 'butt' is that 'square' projects a flat end past the\r
+* end of the line.\r
+* join can be 'miter', 'round', 'bevel'\r
+* dash is an array which sets the dash pattern, is a series of length values, which are the lengths of the\r
+* on and off dashes.\r
+* (2) represents 2 on, 2 off, 2 on , 2 off ...\r
+* (2,1) is 2 on, 1 off, 2 on, 1 off.. etc\r
+* phase is a modifier on the dash pattern which is used to shift the point at which the pattern starts. \r
+*/\r
+function setLineStyle($width=1,$cap='',$join='',$dash='',$phase=0){\r
+\r
+ // this is quite inefficient in that it sets all the parameters whenever 1 is changed, but will fix another day\r
+ $string = '';\r
+ if ($width>0){\r
+ $string.= $width.' w';\r
+ }\r
+ $ca = array('butt'=>0,'round'=>1,'square'=>2);\r
+ if (isset($ca[$cap])){\r
+ $string.= ' '.$ca[$cap].' J';\r
+ }\r
+ $ja = array('miter'=>0,'round'=>1,'bevel'=>2);\r
+ if (isset($ja[$join])){\r
+ $string.= ' '.$ja[$join].' j';\r
+ }\r
+ if (is_array($dash)){\r
+ $string.= ' [';\r
+ foreach ($dash as $len){\r
+ $string.=' '.$len;\r
+ }\r
+ $string.= ' ] '.$phase.' d';\r
+ }\r
+ $this->currentLineStyle = $string;\r
+ $this->objects[$this->currentContents]['c'].="\n".$string;\r
+}\r
+\r
+/**\r
+* draw a polygon, the syntax for this is similar to the GD polygon command\r
+*/\r
+function polygon($p,$np,$f=0){\r
+ $this->objects[$this->currentContents]['c'].="\n";\r
+ $this->objects[$this->currentContents]['c'].=sprintf('%.3f',$p[0]).' '.sprintf('%.3f',$p[1]).' m ';\r
+ for ($i=2;$i<$np*2;$i=$i+2){\r
+ $this->objects[$this->currentContents]['c'].= sprintf('%.3f',$p[$i]).' '.sprintf('%.3f',$p[$i+1]).' l ';\r
+ }\r
+ if ($f==1){\r
+ $this->objects[$this->currentContents]['c'].=' f';\r
+ } else {\r
+ $this->objects[$this->currentContents]['c'].=' S';\r
+ }\r
+}\r
+\r
+/**\r
+* a filled rectangle, note that it is the width and height of the rectangle which are the secondary paramaters, not\r
+* the coordinates of the upper-right corner\r
+*/\r
+function filledRectangle($x1,$y1,$width,$height){\r
+ $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$x1).' '.sprintf('%.3f',$y1).' '.sprintf('%.3f',$width).' '.sprintf('%.3f',$height).' re f';\r
+}\r
+\r
+/**\r
+* draw a rectangle, note that it is the width and height of the rectangle which are the secondary paramaters, not\r
+* the coordinates of the upper-right corner\r
+*/\r
+function rectangle($x1,$y1,$width,$height){\r
+ $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$x1).' '.sprintf('%.3f',$y1).' '.sprintf('%.3f',$width).' '.sprintf('%.3f',$height).' re S';\r
+}\r
+\r
+/**\r
+* add a new page to the document\r
+* this also makes the new page the current active object\r
+*/\r
+function newPage($insert=0,$id=0,$pos='after'){\r
+\r
+ // if there is a state saved, then go up the stack closing them\r
+ // then on the new page, re-open them with the right setings\r
+ \r
+ if ($this->nStateStack){\r
+ for ($i=$this->nStateStack;$i>=1;$i--){\r
+ $this->restoreState($i);\r
+ }\r
+ }\r
+\r
+ $this->numObj++;\r
+ if ($insert){\r
+ // the id from the ezPdf class is the od of the contents of the page, not the page object itself\r
+ // query that object to find the parent\r
+ $rid = $this->objects[$id]['onPage'];\r
+ $opt= array('rid'=>$rid,'pos'=>$pos);\r
+ $this->o_page($this->numObj,'new',$opt);\r
+ } else {\r
+ $this->o_page($this->numObj,'new');\r
+ }\r
+ // if there is a stack saved, then put that onto the page\r
+ if ($this->nStateStack){\r
+ for ($i=1;$i<=$this->nStateStack;$i++){\r
+ $this->saveState($i);\r
+ }\r
+ } \r
+ // and if there has been a stroke or fill colour set, then transfer them\r
+ if ($this->currentColour['r']>=0){\r
+ $this->setColor($this->currentColour['r'],$this->currentColour['g'],$this->currentColour['b'],1);\r
+ }\r
+ if ($this->currentStrokeColour['r']>=0){\r
+ $this->setStrokeColor($this->currentStrokeColour['r'],$this->currentStrokeColour['g'],$this->currentStrokeColour['b'],1);\r
+ }\r
+\r
+ // if there is a line style set, then put this in too\r
+ if (strlen($this->currentLineStyle)){\r
+ $this->objects[$this->currentContents]['c'].="\n".$this->currentLineStyle;\r
+ }\r
+\r
+ // the call to the o_page object set currentContents to the present page, so this can be returned as the page id\r
+ return $this->currentContents;\r
+}\r
+\r
+/**\r
+* output the pdf code, streaming it to the browser\r
+* the relevant headers are set so that hopefully the browser will recognise it\r
+*/\r
+function stream($options=''){\r
+ // setting the options allows the adjustment of the headers\r
+ // values at the moment are:\r
+ // 'Content-Disposition'=>'filename' - sets the filename, though not too sure how well this will \r
+ // work as in my trial the browser seems to use the filename of the php file with .pdf on the end\r
+ // 'Accept-Ranges'=>1 or 0 - if this is not set to 1, then this header is not included, off by default\r
+ // this header seems to have caused some problems despite tha fact that it is supposed to solve\r
+ // them, so I am leaving it off by default.\r
+ // 'compress'=> 1 or 0 - apply content stream compression, this is on (1) by default\r
+ if (!is_array($options)){\r
+ $options=array();\r
+ }\r
+ if ( isset($options['compress']) && $options['compress']==0){\r
+ $tmp = $this->output(1);\r
+ } else {\r
+ $tmp = $this->output();\r
+ }\r
+ header("Content-type: application/pdf");\r
+ header("Content-Length: ".strlen(ltrim($tmp)));\r
+ $fileName = (isset($options['Content-Disposition'])?$options['Content-Disposition']:'file.pdf');\r
+ header("Content-Disposition: inline; filename=".$fileName);\r
+ if (isset($options['Accept-Ranges']) && $options['Accept-Ranges']==1){\r
+ header("Accept-Ranges: ".strlen(ltrim($tmp))); \r
+ }\r
+ echo ltrim($tmp);\r
+}\r
+\r
+/**\r
+* return the height in units of the current font in the given size\r
+*/\r
+function getFontHeight($size){\r
+ if (!$this->numFonts){\r
+ $this->selectFont('./fonts/Helvetica');\r
+ }\r
+ // for the current font, and the given size, what is the height of the font in user units\r
+ $h = $this->fonts[$this->currentFont]['FontBBox'][3]-$this->fonts[$this->currentFont]['FontBBox'][1];\r
+ return $size*$h/1000;\r
+}\r
+\r
+/**\r
+* return the font decender, this will normally return a negative number\r
+* if you add this number to the baseline, you get the level of the bottom of the font\r
+* it is in the pdf user units\r
+*/\r
+function getFontDecender($size){\r
+ // note that this will most likely return a negative value\r
+ if (!$this->numFonts){\r
+ $this->selectFont('./fonts/Helvetica');\r
+ }\r
+ $h = $this->fonts[$this->currentFont]['FontBBox'][1];\r
+ return $size*$h/1000;\r
+}\r
+\r
+/**\r
+* filter the text, this is applied to all text just before being inserted into the pdf document\r
+* it escapes the various things that need to be escaped, and so on\r
+*\r
+* @access private\r
+*/\r
+function filterText($text){\r
+ $text = str_replace('\\','\\\\',$text);\r
+ $text = str_replace('(','\(',$text);\r
+ $text = str_replace(')','\)',$text);\r
+ $text = str_replace('<','<',$text);\r
+ $text = str_replace('>','>',$text);\r
+ $text = str_replace(''','\'',$text);\r
+ $text = str_replace('"','"',$text);\r
+ $text = str_replace('&','&',$text);\r
+\r
+ return $text;\r
+}\r
+\r
+/**\r
+* given a start position and information about how text is to be laid out, calculate where \r
+* on the page the text will end\r
+*\r
+* @access private\r
+*/\r
+function PRVTgetTextPosition($x,$y,$angle,$size,$wa,$text){\r
+ // given this information return an array containing x and y for the end position as elements 0 and 1\r
+ $w = $this->getTextWidth($size,$text);\r
+ // need to adjust for the number of spaces in this text\r
+ $words = explode(' ',$text);\r
+ $nspaces=count($words)-1;\r
+ $w += $wa*$nspaces;\r
+ $a = deg2rad((float)$angle);\r
+ return array(cos($a)*$w+$x,-sin($a)*$w+$y);\r
+}\r
+\r
+/**\r
+* wrapper function for PRVTcheckTextDirective1\r
+*\r
+* @access private\r
+*/\r
+function PRVTcheckTextDirective(&$text,$i,&$f){\r
+ $x=0;\r
+ $y=0;\r
+ return $this->PRVTcheckTextDirective1($text,$i,$f,0,$x,$y);\r
+}\r
+\r
+/**\r
+* checks if the text stream contains a control directive\r
+* if so then makes some changes and returns the number of characters involved in the directive\r
+* this has been re-worked to include everything neccesary to fins the current writing point, so that\r
+* the location can be sent to the callback function if required\r
+* if the directive does not require a font change, then $f should be set to 0\r
+*\r
+* @access private\r
+*/\r
+function PRVTcheckTextDirective1(&$text,$i,&$f,$final,&$x,&$y,$size=0,$angle=0,$wordSpaceAdjust=0){\r
+ $directive = 0;\r
+ $j=$i;\r
+ if ($text[$j]=='<'){\r
+ $j++;\r
+ switch($text[$j]){\r
+ case '/':\r
+ $j++;\r
+ if (strlen($text) <= $j){\r
+ return $directive;\r
+ }\r
+ switch($text[$j]){\r
+ case 'b':\r
+ case 'i':\r
+ $j++;\r
+ if ($text[$j]=='>'){\r
+ $p = strrpos($this->currentTextState,$text[$j-1]);\r
+ if ($p !== false){\r
+ // then there is one to remove\r
+ $this->currentTextState = substr($this->currentTextState,0,$p).substr($this->currentTextState,$p+1);\r
+ }\r
+ $directive=$j-$i+1;\r
+ }\r
+ break;\r
+ case 'c':\r
+ // this this might be a callback function\r
+ $j++;\r
+ $k = strpos($text,'>',$j);\r
+ if ($k!==false && $text[$j]==':'){\r
+ // then this will be treated as a callback directive\r
+ $directive = $k-$i+1;\r
+ $f=0;\r
+ // split the remainder on colons to get the function name and the paramater\r
+ $tmp = substr($text,$j+1,$k-$j-1);\r
+ $b1 = strpos($tmp,':');\r
+ if ($b1!==false){\r
+ $func = substr($tmp,0,$b1);\r
+ $parm = substr($tmp,$b1+1);\r
+ } else {\r
+ $func=$tmp;\r
+ $parm='';\r
+ }\r
+ if (!isset($func) || !strlen(trim($func))){\r
+ $directive=0;\r
+ } else {\r
+ // only call the function if this is the final call\r
+ if ($final){\r
+ // need to assess the text position, calculate the text width to this point\r
+ // can use getTextWidth to find the text width I think\r
+ $tmp = $this->PRVTgetTextPosition($x,$y,$angle,$size,$wordSpaceAdjust,substr($text,0,$i));\r
+ $info = array('x'=>$tmp[0],'y'=>$tmp[1],'angle'=>$angle,'status'=>'end','p'=>$parm,'nCallback'=>$this->nCallback);\r
+ $x=$tmp[0];\r
+ $y=$tmp[1];\r
+ $ret = $this->$func($info);\r
+ if (is_array($ret)){\r
+ // then the return from the callback function could set the position, to start with, later will do font colour, and font\r
+ foreach($ret as $rk=>$rv){\r
+ switch($rk){\r
+ case 'x':\r
+ case 'y':\r
+ $$rk=$rv;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ // also remove from to the stack\r
+ // for simplicity, just take from the end, fix this another day\r
+ $this->nCallback--;\r
+ if ($this->nCallback<0){\r
+ $this->nCallBack=0;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ break;\r
+ case 'b':\r
+ case 'i':\r
+ $j++;\r
+ if ($text[$j]=='>'){\r
+ $this->currentTextState.=$text[$j-1];\r
+ $directive=$j-$i+1;\r
+ }\r
+ break;\r
+ case 'C':\r
+ $noClose=1;\r
+ case 'c':\r
+ // this this might be a callback function\r
+ $j++;\r
+ $k = strpos($text,'>',$j);\r
+ if ($k!==false && $text[$j]==':'){\r
+ // then this will be treated as a callback directive\r
+ $directive = $k-$i+1;\r
+ $f=0;\r
+ // split the remainder on colons to get the function name and the paramater\r
+// $bits = explode(':',substr($text,$j+1,$k-$j-1));\r
+ $tmp = substr($text,$j+1,$k-$j-1);\r
+ $b1 = strpos($tmp,':');\r
+ if ($b1!==false){\r
+ $func = substr($tmp,0,$b1);\r
+ $parm = substr($tmp,$b1+1);\r
+ } else {\r
+ $func=$tmp;\r
+ $parm='';\r
+ }\r
+ if (!isset($func) || !strlen(trim($func))){\r
+ $directive=0;\r
+ } else {\r
+ // only call the function if this is the final call, ie, the one actually doing printing, not measurement\r
+ if ($final){\r
+ // need to assess the text position, calculate the text width to this point\r
+ // can use getTextWidth to find the text width I think\r
+ // also add the text height and decender\r
+ $tmp = $this->PRVTgetTextPosition($x,$y,$angle,$size,$wordSpaceAdjust,substr($text,0,$i));\r
+ $info = array('x'=>$tmp[0],'y'=>$tmp[1],'angle'=>$angle,'status'=>'start','p'=>$parm,'f'=>$func,'height'=>$this->getFontHeight($size),'decender'=>$this->getFontDecender($size));\r
+ $x=$tmp[0];\r
+ $y=$tmp[1];\r
+ if (!isset($noClose) || !$noClose){\r
+ // only add to the stack if this is a small 'c', therefore is a start-stop pair\r
+ $this->nCallback++;\r
+ $info['nCallback']=$this->nCallback;\r
+ $this->callback[$this->nCallback]=$info;\r
+ }\r
+ $ret = $this->$func($info);\r
+ if (is_array($ret)){\r
+ // then the return from the callback function could set the position, to start with, later will do font colour, and font\r
+ foreach($ret as $rk=>$rv){\r
+ switch($rk){\r
+ case 'x':\r
+ case 'y':\r
+ $$rk=$rv;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ } \r
+ return $directive;\r
+}\r
+\r
+/**\r
+* add text to the document, at a specified location, size and angle on the page\r
+*/\r
+function addText($x,$y,$size,$text,$angle=0,$wordSpaceAdjust=0){\r
+ if (!$this->numFonts){$this->selectFont('./fonts/Helvetica');}\r
+\r
+ // if there are any open callbacks, then they should be called, to show the start of the line\r
+ if ($this->nCallback>0){\r
+ for ($i=$this->nCallback;$i>0;$i--){\r
+ // call each function\r
+ $info = array('x'=>$x,'y'=>$y,'angle'=>$angle,'status'=>'sol','p'=>$this->callback[$i]['p'],'nCallback'=>$this->callback[$i]['nCallback'],'height'=>$this->callback[$i]['height'],'decender'=>$this->callback[$i]['decender']);\r
+ $func = $this->callback[$i]['f'];\r
+ $this->$func($info);\r
+ }\r
+ }\r
+ if ($angle==0){\r
+ $this->objects[$this->currentContents]['c'].="\n".'BT '.sprintf('%.3f',$x).' '.sprintf('%.3f',$y).' Td';\r
+ } else {\r
+ $a = deg2rad((float)$angle);\r
+ $tmp = "\n".'BT ';\r
+ $tmp .= sprintf('%.3f',cos($a)).' '.sprintf('%.3f',(-1.0*sin($a))).' '.sprintf('%.3f',sin($a)).' '.sprintf('%.3f',cos($a)).' ';\r
+ $tmp .= sprintf('%.3f',$x).' '.sprintf('%.3f',$y).' Tm';\r
+ $this->objects[$this->currentContents]['c'] .= $tmp;\r
+ }\r
+ if ($wordSpaceAdjust!=0 || $wordSpaceAdjust != $this->wordSpaceAdjust){\r
+ $this->wordSpaceAdjust=$wordSpaceAdjust;\r
+ $this->objects[$this->currentContents]['c'].=' '.sprintf('%.3f',$wordSpaceAdjust).' Tw';\r
+ }\r
+ $len=strlen($text);\r
+ $start=0;\r
+ for ($i=0;$i<$len;$i++){\r
+ $f=1;\r
+ $directive = $this->PRVTcheckTextDirective($text,$i,$f);\r
+ if ($directive){\r
+ // then we should write what we need to\r
+ if ($i>$start){\r
+ $part = substr($text,$start,$i-$start);\r
+ $this->objects[$this->currentContents]['c'].=' /F'.$this->currentFontNum.' '.sprintf('%.1f',$size).' Tf ';\r
+ $this->objects[$this->currentContents]['c'].=' ('.$this->filterText($part).') Tj';\r
+ }\r
+ if ($f){\r
+ // then there was nothing drastic done here, restore the contents\r
+ $this->setCurrentFont();\r
+ } else {\r
+ $this->objects[$this->currentContents]['c'] .= ' ET';\r
+ $f=1;\r
+ $xp=$x;\r
+ $yp=$y;\r
+ $directive = $this->PRVTcheckTextDirective1($text,$i,$f,1,$xp,$yp,$size,$angle,$wordSpaceAdjust);\r
+ \r
+ // restart the text object\r
+ if ($angle==0){\r
+ $this->objects[$this->currentContents]['c'].="\n".'BT '.sprintf('%.3f',$xp).' '.sprintf('%.3f',$yp).' Td';\r
+ } else {\r
+ $a = deg2rad((float)$angle);\r
+ $tmp = "\n".'BT ';\r
+ $tmp .= sprintf('%.3f',cos($a)).' '.sprintf('%.3f',(-1.0*sin($a))).' '.sprintf('%.3f',sin($a)).' '.sprintf('%.3f',cos($a)).' ';\r
+ $tmp .= sprintf('%.3f',$xp).' '.sprintf('%.3f',$yp).' Tm';\r
+ $this->objects[$this->currentContents]['c'] .= $tmp;\r
+ }\r
+ if ($wordSpaceAdjust!=0 || $wordSpaceAdjust != $this->wordSpaceAdjust){\r
+ $this->wordSpaceAdjust=$wordSpaceAdjust;\r
+ $this->objects[$this->currentContents]['c'].=' '.sprintf('%.3f',$wordSpaceAdjust).' Tw';\r
+ }\r
+ }\r
+ // and move the writing point to the next piece of text\r
+ $i=$i+$directive-1;\r
+ $start=$i+1;\r
+ }\r
+ \r
+ }\r
+ if ($start<$len){\r
+ $part = substr($text,$start);\r
+ $this->objects[$this->currentContents]['c'].=' /F'.$this->currentFontNum.' '.sprintf('%.1f',$size).' Tf ';\r
+ $this->objects[$this->currentContents]['c'].=' ('.$this->filterText($part).') Tj';\r
+ }\r
+ $this->objects[$this->currentContents]['c'].=' ET';\r
+\r
+ // if there are any open callbacks, then they should be called, to show the end of the line\r
+ if ($this->nCallback>0){\r
+ for ($i=$this->nCallback;$i>0;$i--){\r
+ // call each function\r
+ $tmp = $this->PRVTgetTextPosition($x,$y,$angle,$size,$wordSpaceAdjust,$text);\r
+ $info = array('x'=>$tmp[0],'y'=>$tmp[1],'angle'=>$angle,'status'=>'eol','p'=>$this->callback[$i]['p'],'nCallback'=>$this->callback[$i]['nCallback'],'height'=>$this->callback[$i]['height'],'decender'=>$this->callback[$i]['decender']);\r
+ $func = $this->callback[$i]['f'];\r
+ $this->$func($info);\r
+ }\r
+ }\r
+\r
+}\r
+\r
+/**\r
+* calculate how wide a given text string will be on a page, at a given size.\r
+* this can be called externally, but is alse used by the other class functions\r
+*/\r
+function getTextWidth($size,$text){\r
+ // this function should not change any of the settings, though it will need to\r
+ // track any directives which change during calculation, so copy them at the start\r
+ // and put them back at the end.\r
+ $store_currentTextState = $this->currentTextState;\r
+\r
+ if (!$this->numFonts){\r
+ $this->selectFont('./fonts/Helvetica');\r
+ }\r
+\r
+ // converts a number or a float to a string so it can get the width\r
+ $text = "$text";\r
+\r
+ // hmm, this is where it all starts to get tricky - use the font information to\r
+ // calculate the width of each character, add them up and convert to user units\r
+ $w=0;\r
+ $len=strlen($text);\r
+ $cf = $this->currentFont;\r
+ for ($i=0;$i<$len;$i++){\r
+ $f=1;\r
+ $directive = $this->PRVTcheckTextDirective($text,$i,$f);\r
+ if ($directive){\r
+ if ($f){\r
+ $this->setCurrentFont();\r
+ $cf = $this->currentFont;\r
+ }\r
+ $i=$i+$directive-1;\r
+ } else {\r
+ $char=ord($text[$i]);\r
+ if (isset($this->fonts[$cf]['differences'][$char])){\r
+ // then this character is being replaced by another\r
+ $name = $this->fonts[$cf]['differences'][$char];\r
+ if (isset($this->fonts[$cf]['C'][$name]['WX'])){\r
+ $w+=$this->fonts[$cf]['C'][$name]['WX'];\r
+ }\r
+ } else if (isset($this->fonts[$cf]['C'][$char]['WX'])){\r
+ $w+=$this->fonts[$cf]['C'][$char]['WX'];\r
+ }\r
+ }\r
+ }\r
+ \r
+ $this->currentTextState = $store_currentTextState;\r
+ $this->setCurrentFont();\r
+\r
+ return $w*$size/1000;\r
+}\r
+\r
+/**\r
+* do a part of the calculation for sorting out the justification of the text\r
+*\r
+* @access private\r
+*/\r
+function PRVTadjustWrapText($text,$actual,$width,&$x,&$adjust,$justification){\r
+ switch ($justification){\r
+ case 'left':\r
+ return;\r
+ break;\r
+ case 'right':\r
+ $x+=$width-$actual;\r
+ break;\r
+ case 'center':\r
+ case 'centre':\r
+ $x+=($width-$actual)/2;\r
+ break;\r
+ case 'full':\r
+ // count the number of words\r
+ $words = explode(' ',$text);\r
+ $nspaces=count($words)-1;\r
+ if ($nspaces>0){\r
+ $adjust = ($width-$actual)/$nspaces;\r
+ } else {\r
+ $adjust=0;\r
+ }\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+* add text to the page, but ensure that it fits within a certain width\r
+* if it does not fit then put in as much as possible, splitting at word boundaries\r
+* and return the remainder.\r
+* justification and angle can also be specified for the text\r
+*/\r
+function addTextWrap($x,$y,$width,$size,$text,$justification='left',$angle=0,$test=0){\r
+ // this will display the text, and if it goes beyond the width $width, will backtrack to the \r
+ // previous space or hyphen, and return the remainder of the text.\r
+\r
+ // $justification can be set to 'left','right','center','centre','full'\r
+\r
+ // need to store the initial text state, as this will change during the width calculation\r
+ // but will need to be re-set before printing, so that the chars work out right\r
+ $store_currentTextState = $this->currentTextState;\r
+\r
+ if (!$this->numFonts){$this->selectFont('./fonts/Helvetica');}\r
+ if ($width<=0){\r
+ // error, pretend it printed ok, otherwise risking a loop\r
+ return '';\r
+ }\r
+ $w=0;\r
+ $break=0;\r
+ $breakWidth=0;\r
+ $len=strlen($text);\r
+ $cf = $this->currentFont;\r
+ $tw = $width/$size*1000;\r
+ for ($i=0;$i<$len;$i++){\r
+ $f=1;\r
+ $directive = $this->PRVTcheckTextDirective($text,$i,$f);\r
+ if ($directive){\r
+ if ($f){\r
+ $this->setCurrentFont();\r
+ $cf = $this->currentFont;\r
+ }\r
+ $i=$i+$directive-1;\r
+ } else {\r
+ $cOrd = ord($text[$i]);\r
+ if (isset($this->fonts[$cf]['differences'][$cOrd])){\r
+ // then this character is being replaced by another\r
+ $cOrd2 = $this->fonts[$cf]['differences'][$cOrd];\r
+ } else {\r
+ $cOrd2 = $cOrd;\r
+ }\r
+ \r
+ if (isset($this->fonts[$cf]['C'][$cOrd2]['WX'])){\r
+ $w+=$this->fonts[$cf]['C'][$cOrd2]['WX'];\r
+ }\r
+ if ($w>$tw){\r
+ // then we need to truncate this line\r
+ if ($break>0){\r
+ // then we have somewhere that we can split :)\r
+ if ($text[$break]==' '){\r
+ $tmp = substr($text,0,$break);\r
+ } else {\r
+ $tmp = substr($text,0,$break+1);\r
+ }\r
+ $adjust=0;\r
+ $this->PRVTadjustWrapText($tmp,$breakWidth,$width,$x,$adjust,$justification);\r
+\r
+ // reset the text state\r
+ $this->currentTextState = $store_currentTextState;\r
+ $this->setCurrentFont();\r
+ if (!$test){\r
+ $this->addText($x,$y,$size,$tmp,$angle,$adjust);\r
+ }\r
+ return substr($text,$break+1);\r
+ } else {\r
+ // just split before the current character\r
+ $tmp = substr($text,0,$i);\r
+ $adjust=0;\r
+ $ctmp=ord($text[$i]);\r
+ if (isset($this->fonts[$cf]['differences'][$ctmp])){\r
+ $ctmp=$this->fonts[$cf]['differences'][$ctmp];\r
+ }\r
+ $tmpw=($w-$this->fonts[$cf]['C'][$ctmp]['WX'])*$size/1000;\r
+ $this->PRVTadjustWrapText($tmp,$tmpw,$width,$x,$adjust,$justification);\r
+ // reset the text state\r
+ $this->currentTextState = $store_currentTextState;\r
+ $this->setCurrentFont();\r
+ if (!$test){\r
+ $this->addText($x,$y,$size,$tmp,$angle,$adjust);\r
+ }\r
+ return substr($text,$i);\r
+ }\r
+ }\r
+ if ($text[$i]=='-'){\r
+ $break=$i;\r
+ $breakWidth = $w*$size/1000;\r
+ }\r
+ if ($text[$i]==' '){\r
+ $break=$i;\r
+ $ctmp=ord($text[$i]);\r
+ if (isset($this->fonts[$cf]['differences'][$ctmp])){\r
+ $ctmp=$this->fonts[$cf]['differences'][$ctmp];\r
+ }\r
+ $breakWidth = ($w-$this->fonts[$cf]['C'][$ctmp]['WX'])*$size/1000;\r
+ }\r
+ }\r
+ }\r
+ // then there was no need to break this line\r
+ if ($justification=='full'){\r
+ $justification='left';\r
+ }\r
+ $adjust=0;\r
+ $tmpw=$w*$size/1000;\r
+ $this->PRVTadjustWrapText($text,$tmpw,$width,$x,$adjust,$justification);\r
+ // reset the text state\r
+ $this->currentTextState = $store_currentTextState;\r
+ $this->setCurrentFont();\r
+ if (!$test){\r
+ $this->addText($x,$y,$size,$text,$angle,$adjust,$angle);\r
+ }\r
+ return '';\r
+}\r
+\r
+/**\r
+* this will be called at a new page to return the state to what it was on the \r
+* end of the previous page, before the stack was closed down\r
+* This is to get around not being able to have open 'q' across pages\r
+*\r
+*/\r
+function saveState($pageEnd=0){\r
+ if ($pageEnd){\r
+ // this will be called at a new page to return the state to what it was on the \r
+ // end of the previous page, before the stack was closed down\r
+ // This is to get around not being able to have open 'q' across pages\r
+ $opt = $this->stateStack[$pageEnd]; // ok to use this as stack starts numbering at 1\r
+ $this->setColor($opt['col']['r'],$opt['col']['g'],$opt['col']['b'],1);\r
+ $this->setStrokeColor($opt['str']['r'],$opt['str']['g'],$opt['str']['b'],1);\r
+ $this->objects[$this->currentContents]['c'].="\n".$opt['lin'];\r
+// $this->currentLineStyle = $opt['lin'];\r
+ } else {\r
+ $this->nStateStack++;\r
+ $this->stateStack[$this->nStateStack]=array(\r
+ 'col'=>$this->currentColour\r
+ ,'str'=>$this->currentStrokeColour\r
+ ,'lin'=>$this->currentLineStyle\r
+ );\r
+ }\r
+ $this->objects[$this->currentContents]['c'].="\nq";\r
+}\r
+\r
+/**\r
+* restore a previously saved state\r
+*/\r
+function restoreState($pageEnd=0){\r
+ if (!$pageEnd){\r
+ $n = $this->nStateStack;\r
+ $this->currentColour = $this->stateStack[$n]['col'];\r
+ $this->currentStrokeColour = $this->stateStack[$n]['str'];\r
+ $this->objects[$this->currentContents]['c'].="\n".$this->stateStack[$n]['lin'];\r
+ $this->currentLineStyle = $this->stateStack[$n]['lin'];\r
+ unset($this->stateStack[$n]);\r
+ $this->nStateStack--;\r
+ }\r
+ $this->objects[$this->currentContents]['c'].="\nQ";\r
+}\r
+\r
+/**\r
+* make a loose object, the output will go into this object, until it is closed, then will revert to\r
+* the current one.\r
+* this object will not appear until it is included within a page.\r
+* the function will return the object number\r
+*/\r
+function openObject(){\r
+ $this->nStack++;\r
+ $this->stack[$this->nStack]=array('c'=>$this->currentContents,'p'=>$this->currentPage);\r
+ // add a new object of the content type, to hold the data flow\r
+ $this->numObj++;\r
+ $this->o_contents($this->numObj,'new');\r
+ $this->currentContents=$this->numObj;\r
+ $this->looseObjects[$this->numObj]=1;\r
+ \r
+ return $this->numObj;\r
+}\r
+\r
+/**\r
+* open an existing object for editing\r
+*/\r
+function reopenObject($id){\r
+ $this->nStack++;\r
+ $this->stack[$this->nStack]=array('c'=>$this->currentContents,'p'=>$this->currentPage);\r
+ $this->currentContents=$id;\r
+ // also if this object is the primary contents for a page, then set the current page to its parent\r
+ if (isset($this->objects[$id]['onPage'])){\r
+ $this->currentPage = $this->objects[$id]['onPage'];\r
+ }\r
+}\r
+\r
+/**\r
+* close an object\r
+*/\r
+function closeObject(){\r
+ // close the object, as long as there was one open in the first place, which will be indicated by\r
+ // an objectId on the stack.\r
+ if ($this->nStack>0){\r
+ $this->currentContents=$this->stack[$this->nStack]['c'];\r
+ $this->currentPage=$this->stack[$this->nStack]['p'];\r
+ $this->nStack--;\r
+ // easier to probably not worry about removing the old entries, they will be overwritten\r
+ // if there are new ones.\r
+ }\r
+}\r
+\r
+/**\r
+* stop an object from appearing on pages from this point on\r
+*/\r
+function stopObject($id){\r
+ // if an object has been appearing on pages up to now, then stop it, this page will\r
+ // be the last one that could contian it.\r
+ if (isset($this->addLooseObjects[$id])){\r
+ $this->addLooseObjects[$id]='';\r
+ }\r
+}\r
+\r
+/**\r
+* after an object has been created, it wil only show if it has been added, using this function.\r
+*/\r
+function addObject($id,$options='add'){\r
+ // add the specified object to the page\r
+ if (isset($this->looseObjects[$id]) && $this->currentContents!=$id){\r
+ // then it is a valid object, and it is not being added to itself\r
+ switch($options){\r
+ case 'all':\r
+ // then this object is to be added to this page (done in the next block) and \r
+ // all future new pages. \r
+ $this->addLooseObjects[$id]='all';\r
+ case 'add':\r
+ if (isset($this->objects[$this->currentContents]['onPage'])){\r
+ // then the destination contents is the primary for the page\r
+ // (though this object is actually added to that page)\r
+ $this->o_page($this->objects[$this->currentContents]['onPage'],'content',$id);\r
+ }\r
+ break;\r
+ case 'even':\r
+ $this->addLooseObjects[$id]='even';\r
+ $pageObjectId=$this->objects[$this->currentContents]['onPage'];\r
+ if ($this->objects[$pageObjectId]['info']['pageNum']%2==0){\r
+ $this->addObject($id); // hacky huh :)\r
+ }\r
+ break;\r
+ case 'odd':\r
+ $this->addLooseObjects[$id]='odd';\r
+ $pageObjectId=$this->objects[$this->currentContents]['onPage'];\r
+ if ($this->objects[$pageObjectId]['info']['pageNum']%2==1){\r
+ $this->addObject($id); // hacky huh :)\r
+ }\r
+ break;\r
+ case 'next':\r
+ $this->addLooseObjects[$id]='all';\r
+ break;\r
+ case 'nexteven':\r
+ $this->addLooseObjects[$id]='even';\r
+ break;\r
+ case 'nextodd':\r
+ $this->addLooseObjects[$id]='odd';\r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+* add content to the documents info object\r
+*/\r
+function addInfo($label,$value=0){\r
+ // this will only work if the label is one of the valid ones.\r
+ // modify this so that arrays can be passed as well.\r
+ // if $label is an array then assume that it is key=>value pairs\r
+ // else assume that they are both scalar, anything else will probably error\r
+ if (is_array($label)){\r
+ foreach ($label as $l=>$v){\r
+ $this->o_info($this->infoObject,$l,$v);\r
+ }\r
+ } else {\r
+ $this->o_info($this->infoObject,$label,$value);\r
+ }\r
+}\r
+\r
+/**\r
+* set the viewer preferences of the document, it is up to the browser to obey these.\r
+*/\r
+function setPreferences($label,$value=0){\r
+ // this will only work if the label is one of the valid ones.\r
+ if (is_array($label)){\r
+ foreach ($label as $l=>$v){\r
+ $this->o_catalog($this->catalogId,'viewerPreferences',array($l=>$v));\r
+ }\r
+ } else {\r
+ $this->o_catalog($this->catalogId,'viewerPreferences',array($label=>$value));\r
+ }\r
+}\r
+\r
+/**\r
+* extract an integer from a position in a byte stream\r
+*\r
+* @access private\r
+*/\r
+function PRVT_getBytes(&$data,$pos,$num){\r
+ // return the integer represented by $num bytes from $pos within $data\r
+ $ret=0;\r
+ for ($i=0;$i<$num;$i++){\r
+ $ret=$ret*256;\r
+ $ret+=ord($data[$pos+$i]);\r
+ }\r
+ return $ret;\r
+}\r
+\r
+/**\r
+* add a PNG image into the document, from a file\r
+* this should work with remote files\r
+*/\r
+function addPngFromFile($file,$x,$y,$w=0,$h=0){\r
+ // read in a png file, interpret it, then add to the system\r
+ $error=0;\r
+ $tmp = get_magic_quotes_runtime();\r
+ set_magic_quotes_runtime(0);\r
+ $fp = @fopen($file,'rb');\r
+ if ($fp){\r
+ $data='';\r
+ while(!feof($fp)){\r
+ $data .= fread($fp,1024);\r
+ }\r
+ fclose($fp);\r
+ } else {\r
+ $error = 1;\r
+ $errormsg = 'trouble opening file: '.$file;\r
+ }\r
+ set_magic_quotes_runtime($tmp);\r
+ \r
+ if (!$error){\r
+ $header = chr(137).chr(80).chr(78).chr(71).chr(13).chr(10).chr(26).chr(10);\r
+ if (substr($data,0,8)!=$header){\r
+ $error=1;\r
+ $errormsg = 'this file does not have a valid header';\r
+ }\r
+ }\r
+\r
+ if (!$error){\r
+ // set pointer\r
+ $p = 8;\r
+ $len = strlen($data);\r
+ // cycle through the file, identifying chunks\r
+ $haveHeader=0;\r
+ $info=array();\r
+ $idata='';\r
+ $pdata='';\r
+ while ($p<$len){\r
+ $chunkLen = $this->PRVT_getBytes($data,$p,4);\r
+ $chunkType = substr($data,$p+4,4);\r
+// echo $chunkType.' - '.$chunkLen.'<br>';\r
+ \r
+ switch($chunkType){\r
+ case 'IHDR':\r
+ // this is where all the file information comes from\r
+ $info['width']=$this->PRVT_getBytes($data,$p+8,4);\r
+ $info['height']=$this->PRVT_getBytes($data,$p+12,4);\r
+ $info['bitDepth']=ord($data[$p+16]);\r
+ $info['colorType']=ord($data[$p+17]);\r
+ $info['compressionMethod']=ord($data[$p+18]);\r
+ $info['filterMethod']=ord($data[$p+19]);\r
+ $info['interlaceMethod']=ord($data[$p+20]);\r
+//print_r($info);\r
+ $haveHeader=1;\r
+ if ($info['compressionMethod']!=0){\r
+ $error=1;\r
+ $errormsg = 'unsupported compression method';\r
+ }\r
+ if ($info['filterMethod']!=0){\r
+ $error=1;\r
+ $errormsg = 'unsupported filter method';\r
+ }\r
+ break;\r
+ case 'PLTE':\r
+ $pdata.=substr($data,$p+8,$chunkLen);\r
+ break;\r
+ case 'IDAT':\r
+ $idata.=substr($data,$p+8,$chunkLen);\r
+ break;\r
+ case 'tRNS': \r
+ //this chunk can only occur once and it must occur after the PLTE chunk and before IDAT chunk \r
+ //print "tRNS found, color type = ".$info['colorType']."<BR>"; \r
+ $transparency = array();\r
+ if ($info['colorType'] == 3) { // indexed color, rbg \r
+ /* corresponding to entries in the plte chunk \r
+ Alpha for palette index 0: 1 byte \r
+ Alpha for palette index 1: 1 byte \r
+ ...etc... \r
+ */ \r
+ // there will be one entry for each palette entry. up until the last non-opaque entry.\r
+ // set up an array, stretching over all palette entries which will be o (opaque) or 1 (transparent)\r
+ $transparency['type']='indexed';\r
+ $numPalette = strlen($pdata)/3;\r
+ $trans=0;\r
+ for ($i=$chunkLen;$i>=0;$i--){\r
+ if (ord($data[$p+8+$i])==0){\r
+ $trans=$i;\r
+ }\r
+ }\r
+ $transparency['data'] = $trans;\r
+ \r
+ } elseif($info['colorType'] == 0) { // grayscale \r
+ /* corresponding to entries in the plte chunk \r
+ Gray: 2 bytes, range 0 .. (2^bitdepth)-1 \r
+ */ \r
+// $transparency['grayscale']=$this->PRVT_getBytes($data,$p+8,2); // g = grayscale \r
+ $transparency['type']='indexed';\r
+ $transparency['data'] = ord($data[$p+8+1]);\r
+ \r
+ } elseif($info['colorType'] == 2) { // truecolor \r
+ /* corresponding to entries in the plte chunk \r
+ Red: 2 bytes, range 0 .. (2^bitdepth)-1 \r
+ Green: 2 bytes, range 0 .. (2^bitdepth)-1 \r
+ Blue: 2 bytes, range 0 .. (2^bitdepth)-1 \r
+ */ \r
+ $transparency['r']=$this->PRVT_getBytes($data,$p+8,2); // r from truecolor \r
+ $transparency['g']=$this->PRVT_getBytes($data,$p+10,2); // g from truecolor \r
+ $transparency['b']=$this->PRVT_getBytes($data,$p+12,2); // b from truecolor \r
+ \r
+ } else { \r
+ //unsupported transparency type \r
+ } \r
+ // KS End new code \r
+ break; \r
+ default:\r
+ break;\r
+ }\r
+ \r
+ $p += $chunkLen+12;\r
+ }\r
+ \r
+ if(!$haveHeader){\r
+ $error = 1;\r
+ $errormsg = 'information header is missing';\r
+ }\r
+ if (isset($info['interlaceMethod']) && $info['interlaceMethod']){\r
+ $error = 1;\r
+ $errormsg = 'There appears to be no support for interlaced images in pdf.';\r
+ }\r
+ }\r
+\r
+ if (!$error && $info['bitDepth'] > 8){\r
+ $error = 1;\r
+ $errormsg = 'only bit depth of 8 or less is supported';\r
+ }\r
+\r
+ if (!$error){\r
+ if ($info['colorType']!=2 && $info['colorType']!=0 && $info['colorType']!=3){\r
+ $error = 1;\r
+ $errormsg = 'transparancey alpha channel not supported, transparency only supported for palette images.';\r
+ } else {\r
+ switch ($info['colorType']){\r
+ case 3:\r
+ $color = 'DeviceRGB';\r
+ $ncolor=1;\r
+ break;\r
+ case 2:\r
+ $color = 'DeviceRGB';\r
+ $ncolor=3;\r
+ break;\r
+ case 0:\r
+ $color = 'DeviceGray';\r
+ $ncolor=1;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ if ($error){\r
+ $this->addMessage('PNG error - ('.$file.') '.$errormsg);\r
+ return;\r
+ }\r
+ if ($w==0){\r
+ $w=$h/$info['height']*$info['width'];\r
+ }\r
+ if ($h==0){\r
+ $h=$w*$info['height']/$info['width'];\r
+ }\r
+//print_r($info);\r
+ // so this image is ok... add it in.\r
+ $this->numImages++;\r
+ $im=$this->numImages;\r
+ $label='I'.$im;\r
+ $this->numObj++;\r
+// $this->o_image($this->numObj,'new',array('label'=>$label,'data'=>$idata,'iw'=>$w,'ih'=>$h,'type'=>'png','ic'=>$info['width']));\r
+ $options = array('label'=>$label,'data'=>$idata,'bitsPerComponent'=>$info['bitDepth'],'pdata'=>$pdata\r
+ ,'iw'=>$info['width'],'ih'=>$info['height'],'type'=>'png','color'=>$color,'ncolor'=>$ncolor);\r
+ if (isset($transparency)){\r
+ $options['transparency']=$transparency;\r
+ }\r
+ $this->o_image($this->numObj,'new',$options);\r
+\r
+ $this->objects[$this->currentContents]['c'].="\nq";\r
+ $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$w)." 0 0 ".sprintf('%.3f',$h)." ".sprintf('%.3f',$x)." ".sprintf('%.3f',$y)." cm";\r
+ $this->objects[$this->currentContents]['c'].="\n/".$label.' Do';\r
+ $this->objects[$this->currentContents]['c'].="\nQ";\r
+}\r
+\r
+/**\r
+* add a JPEG image into the document, from a file\r
+*/\r
+function addJpegFromFile($img,$x,$y,$w=0,$h=0){\r
+ // attempt to add a jpeg image straight from a file, using no GD commands\r
+ // note that this function is unable to operate on a remote file.\r
+\r
+ if (!file_exists($img)){\r
+ return;\r
+ }\r
+\r
+ $tmp=getimagesize($img);\r
+ $imageWidth=$tmp[0];\r
+ $imageHeight=$tmp[1];\r
+\r
+ if (isset($tmp['channels'])){\r
+ $channels = $tmp['channels'];\r
+ } else {\r
+ $channels = 3;\r
+ }\r
+\r
+ if ($w<=0 && $h<=0){\r
+ $w=$imageWidth;\r
+ }\r
+ if ($w==0){\r
+ $w=$h/$imageHeight*$imageWidth;\r
+ }\r
+ if ($h==0){\r
+ $h=$w*$imageHeight/$imageWidth;\r
+ }\r
+\r
+ $fp=fopen($img,'rb');\r
+\r
+ $tmp = get_magic_quotes_runtime();\r
+ set_magic_quotes_runtime(0);\r
+ $data = fread($fp,filesize($img));\r
+ set_magic_quotes_runtime($tmp);\r
+ \r
+ fclose($fp);\r
+\r
+ $this->addJpegImage_common($data,$x,$y,$w,$h,$imageWidth,$imageHeight,$channels);\r
+}\r
+\r
+/**\r
+* add an image into the document, from a GD object\r
+* this function is not all that reliable, and I would probably encourage people to use \r
+* the file based functions\r
+*/\r
+function addImage(&$img,$x,$y,$w=0,$h=0,$quality=75){\r
+ // add a new image into the current location, as an external object\r
+ // add the image at $x,$y, and with width and height as defined by $w & $h\r
+ \r
+ // note that this will only work with full colour images and makes them jpg images for display\r
+ // later versions could present lossless image formats if there is interest.\r
+ \r
+ // there seems to be some problem here in that images that have quality set above 75 do not appear\r
+ // not too sure why this is, but in the meantime I have restricted this to 75. \r
+ if ($quality>75){\r
+ $quality=75;\r
+ }\r
+\r
+ // if the width or height are set to zero, then set the other one based on keeping the image\r
+ // height/width ratio the same, if they are both zero, then give up :)\r
+ $imageWidth=imagesx($img);\r
+ $imageHeight=imagesy($img);\r
+ \r
+ if ($w<=0 && $h<=0){\r
+ return;\r
+ }\r
+ if ($w==0){\r
+ $w=$h/$imageHeight*$imageWidth;\r
+ }\r
+ if ($h==0){\r
+ $h=$w*$imageHeight/$imageWidth;\r
+ }\r
+ \r
+ // gotta get the data out of the img..\r
+\r
+ // so I write to a temp file, and then read it back.. soo ugly, my apologies.\r
+ $tmpDir='/tmp';\r
+ $tmpName=tempnam($tmpDir,'img');\r
+ imagejpeg($img,$tmpName,$quality);\r
+ $fp=fopen($tmpName,'rb');\r
+\r
+ $tmp = get_magic_quotes_runtime();\r
+ set_magic_quotes_runtime(0);\r
+ $fp = @fopen($tmpName,'rb');\r
+ if ($fp){\r
+ $data='';\r
+ while(!feof($fp)){\r
+ $data .= fread($fp,1024);\r
+ }\r
+ fclose($fp);\r
+ } else {\r
+ $error = 1;\r
+ $errormsg = 'trouble opening file';\r
+ }\r
+// $data = fread($fp,filesize($tmpName));\r
+ set_magic_quotes_runtime($tmp);\r
+// fclose($fp);\r
+ unlink($tmpName);\r
+ $this->addJpegImage_common($data,$x,$y,$w,$h,$imageWidth,$imageHeight);\r
+}\r
+\r
+/**\r
+* common code used by the two JPEG adding functions\r
+*\r
+* @access private\r
+*/\r
+function addJpegImage_common(&$data,$x,$y,$w=0,$h=0,$imageWidth,$imageHeight,$channels=3){\r
+ // note that this function is not to be called externally\r
+ // it is just the common code between the GD and the file options\r
+ $this->numImages++;\r
+ $im=$this->numImages;\r
+ $label='I'.$im;\r
+ $this->numObj++;\r
+ $this->o_image($this->numObj,'new',array('label'=>$label,'data'=>$data,'iw'=>$imageWidth,'ih'=>$imageHeight,'channels'=>$channels));\r
+\r
+ $this->objects[$this->currentContents]['c'].="\nq";\r
+ $this->objects[$this->currentContents]['c'].="\n".sprintf('%.3f',$w)." 0 0 ".sprintf('%.3f',$h)." ".sprintf('%.3f',$x)." ".sprintf('%.3f',$y)." cm";\r
+ $this->objects[$this->currentContents]['c'].="\n/".$label.' Do';\r
+ $this->objects[$this->currentContents]['c'].="\nQ";\r
+}\r
+\r
+/**\r
+* specify where the document should open when it first starts\r
+*/\r
+function openHere($style,$a=0,$b=0,$c=0){\r
+ // this function will open the document at a specified page, in a specified style\r
+ // the values for style, and the required paramters are:\r
+ // 'XYZ' left, top, zoom\r
+ // 'Fit'\r
+ // 'FitH' top\r
+ // 'FitV' left\r
+ // 'FitR' left,bottom,right\r
+ // 'FitB'\r
+ // 'FitBH' top\r
+ // 'FitBV' left\r
+ $this->numObj++;\r
+ $this->o_destination($this->numObj,'new',array('page'=>$this->currentPage,'type'=>$style,'p1'=>$a,'p2'=>$b,'p3'=>$c));\r
+ $id = $this->catalogId;\r
+ $this->o_catalog($id,'openHere',$this->numObj);\r
+}\r
+\r
+/**\r
+* create a labelled destination within the document\r
+*/\r
+function addDestination($label,$style,$a=0,$b=0,$c=0){\r
+ // associates the given label with the destination, it is done this way so that a destination can be specified after\r
+ // it has been linked to\r
+ // styles are the same as the 'openHere' function\r
+ $this->numObj++;\r
+ $this->o_destination($this->numObj,'new',array('page'=>$this->currentPage,'type'=>$style,'p1'=>$a,'p2'=>$b,'p3'=>$c));\r
+ $id = $this->numObj;\r
+ // store the label->idf relationship, note that this means that labels can be used only once\r
+ $this->destinations["$label"]=$id;\r
+}\r
+\r
+/**\r
+* define font families, this is used to initialize the font families for the default fonts\r
+* and for the user to add new ones for their fonts. The default bahavious can be overridden should\r
+* that be desired.\r
+*/\r
+function setFontFamily($family,$options=''){\r
+ if (!is_array($options)){\r
+ if ($family=='init'){\r
+ // set the known family groups\r
+ // these font families will be used to enable bold and italic markers to be included\r
+ // within text streams. html forms will be used... <b></b> <i></i>\r
+ $this->fontFamilies['Helvetica.afm']=array(\r
+ 'b'=>'Helvetica-Bold.afm'\r
+ ,'i'=>'Helvetica-Oblique.afm'\r
+ ,'bi'=>'Helvetica-BoldOblique.afm'\r
+ ,'ib'=>'Helvetica-BoldOblique.afm'\r
+ );\r
+ $this->fontFamilies['Courier.afm']=array(\r
+ 'b'=>'Courier-Bold.afm'\r
+ ,'i'=>'Courier-Oblique.afm'\r
+ ,'bi'=>'Courier-BoldOblique.afm'\r
+ ,'ib'=>'Courier-BoldOblique.afm'\r
+ );\r
+ $this->fontFamilies['Times-Roman.afm']=array(\r
+ 'b'=>'Times-Bold.afm'\r
+ ,'i'=>'Times-Italic.afm'\r
+ ,'bi'=>'Times-BoldItalic.afm'\r
+ ,'ib'=>'Times-BoldItalic.afm'\r
+ );\r
+ }\r
+ } else {\r
+ // the user is trying to set a font family\r
+ // note that this can also be used to set the base ones to something else\r
+ if (strlen($family)){\r
+ $this->fontFamilies[$family] = $options;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+* used to add messages for use in debugging\r
+*/\r
+function addMessage($message){\r
+ $this->messages.=$message."\n";\r
+}\r
+\r
+/**\r
+* a few functions which should allow the document to be treated transactionally.\r
+*/\r
+function transaction($action){\r
+ switch ($action){\r
+ case 'start':\r
+ // store all the data away into the checkpoint variable\r
+ $data = get_object_vars($this);\r
+ $this->checkpoint = $data;\r
+ unset($data);\r
+ break;\r
+ case 'commit':\r
+ if (is_array($this->checkpoint) && isset($this->checkpoint['checkpoint'])){\r
+ $tmp = $this->checkpoint['checkpoint'];\r
+ $this->checkpoint = $tmp;\r
+ unset($tmp);\r
+ } else {\r
+ $this->checkpoint='';\r
+ }\r
+ break;\r
+ case 'rewind':\r
+ // do not destroy the current checkpoint, but move us back to the state then, so that we can try again\r
+ if (is_array($this->checkpoint)){\r
+ // can only abort if were inside a checkpoint\r
+ $tmp = $this->checkpoint;\r
+ foreach ($tmp as $k=>$v){\r
+ if ($k != 'checkpoint'){\r
+ $this->$k=$v;\r
+ }\r
+ }\r
+ unset($tmp);\r
+ }\r
+ break;\r
+ case 'abort':\r
+ if (is_array($this->checkpoint)){\r
+ // can only abort if were inside a checkpoint\r
+ $tmp = $this->checkpoint;\r
+ foreach ($tmp as $k=>$v){\r
+ $this->$k=$v;\r
+ }\r
+ unset($tmp);\r
+ }\r
+ break;\r
+ }\r
+\r
+}\r
+\r
+} // end of class\r
+\r
+?>
\ No newline at end of file
--- /dev/null
+[conf]
+applicationName = "Coupons"
+minYear = 2012
+defaultPage = 43
+
+[listing type]
+singular = "Coupon"
+plural = "Coupons"
--- /dev/null
+#coupons {margin-left: 12px;}
+
+.couponheader {
+ border-bottom: 2px solid #B5B292;
+ font-size: 16px;
+ color: #369;
+ font-weight: bold;
+ margin-top: 1em;
+ }
+.couponitem {
+ background-color: #fff;
+ border: 1px dashed #B5B292;
+ font-weight:normal;
+ color: #369;
+ margin: 5px;
+ font-size: 12px;
+ text-align: center;
+ height: 1%;
+ overflow: hidden;
+ float: left;
+ position: relative;
+ width: 256px;
+ }
+.couponitem strong {
+ display: block;
+ font-size: 16px;
+ display: block;
+ margin: 12px auto;
+ }
+.couponitem a {display: block; font-size: 12px;}
+.couponitem img {
+
+ margin: 0 auto;
+ display: block;
+ }
+.couponcontainer {
+ text-align: left;
+ height: 1%;
+ overflow: hidden;
+ }
+.couponitem .couponlogo {
+ margin-top: 10px;
+ }
+.couponcontainer h2 {
+ font-size: 16px; color: black;
+ clear: left;
+ }
+.couponcatheader {font-size: 16px; color: #369; font-weight: bold;}
+.couponcontainer p {
+ margin: 0.5em 22px !important;
+ text-align: left;
+ }
+.expire_date {
+ float: right;
+ margin: 12px;
+ }
+.coupon-url {
+ float: left;
+ margin: 12px;
+ }
+
+.newBackground {
+background-color: #B5B292; color: #fff; font-weight: bold; padding: 5px; font-size: 13px; text-align: left;
+}
+.oldBackground {
+background-color: #E7E7D5; color: #3D1006; font-weight: bold; padding: 5px; font-size: 13px; text-align: left;
+}
+.changeParent {display: block;}
+
+.coupon-buttons {
+ text-align: center;
+ padding: 6px;
+ position: relative;
+ clear: left;
+ margin-top: 12px;
+ }
+.coupon-buttons input { padding: auto 12px;}
+.couponDivider {
+ clear: left;
+}
+.couponRow {clear:both;}
--- /dev/null
+var CouponToolbox =
+{
+ init: function()
+ {
+ $(".switchable").click(function() {
+ $(this).next().toggle();
+ });
+
+ CouponToolbox.bindDeletableEvents();
+
+ $("#add-coupon-category").click(function(event) {
+ event.preventDefault();
+ var value = $("#coupon_cat").val();
+ var name = $("#coupon_cat :selected").text();
+ html = '<div>';
+ html += '<a href="#" class="deletable">Delete</a> ';
+ html += name + ' <input type="hidden" name="couponCats[]" value="'+value+'">';
+ html += '</div>';
+ $("#list-coupons-info").append(html);
+
+ CouponToolbox.bindDeletableEvents();
+ });
+ },
+
+ bindDeletableEvents: function()
+ {
+ $(".deletable").unbind('click');
+
+ $(".deletable").click(function(event) {
+ event.preventDefault();
+ $(this).parent().html('');
+ });
+ }
+};
+
+$(document).ready(CouponToolbox.init);
--- /dev/null
+var Coupons =
+{
+ init: function()
+ {
+ $('input[name="printSel"]').click(function(){
+ var hasSelected = false;
+ $('input:checkbox[name*="coupon_"]').each(function(){
+ if ($(this).is(':checked')) {
+ hasSelected = true;
+ }
+ });
+ if (!hasSelected) {
+ alert('Please Select at least one coupon!');
+ return false;
+ } else {
+ return true;
+ }
+ });
+ }
+};
+
+$(document).ready(Coupons.init);
--- /dev/null
+<?php
+include_once '../../setup.phtml';
+include_once BASE.'classes/class_db.inc';
+include_once 'class.ezpdf.php';
+//extract($_QUEST);
+
+$dbh = Toolkit_Database::getInstance();
+$params = array(
+ "c.active = true"
+);
+foreach ($_POST as $pKey => $pVal) {
+ if (preg_match('/coupon_([0-9]*)/', $pKey, $coupon_part)) {
+ $coupon_arr[] = $coupon_part[1];
+ }
+}
+if (is_array($coupon_arr) && !$_REQUEST['printAll']) {
+ $params[] = "c.id IN (".implode(",", $coupon_arr).") ";
+}
+if (isset($_REQUEST['coupons_catid']) && ctype_digit($_REQUEST['coupons_catid'])) {
+ $params[] = "cc.id = {$_REQUEST['coupons_catid']}";
+}
+if (!empty($_REQUEST['months']) && preg_match('/([0-9]{2}) ([0-9]{4})/', $_REQUEST['months'], $found)) {
+ try {
+ $date = new DateTime($found[2] . '-' . $found[1] . '-01');
+ $params[] = "(DATE '{$date->format('Y-m-d')}', DATE '{$date->format('Y-m-t')}') OVERLAPS (c.sdate, c.edate)";
+ } catch(Exception $e) {
+ Toolkit_Common::handleError($e);
+ }
+} else {
+ $params[] = 'CURRENT_DATE BETWEEN c.sdate AND c.edate';
+}
+if ($_REQUEST['member_id'] && ctype_digit($_REQUEST['member_id'])) {
+ $params[] = "c.member = {$_REQUEST['member_id']}";
+}
+
+// Determine if coupon category filter has any entries
+$sql = "
+ SELECT *
+ FROM coupon_categories2toolbox_pages
+ WHERE page = :catid";
+$stmt = $dbh->prepare($sql);
+$stmt->bindParam(
+ ':catid',
+ $_REQUEST['catid'],
+ PDO::PARAM_INT
+);
+
+$stmt->execute();
+$ccats = ($stmt->rowCount() > 0);
+
+// If using coupon category filters
+if ($ccats) {
+ $sql = "
+ SELECT c.*, c.title as header, cc.name as category,
+ date_part('epoch', c.edate) as expire
+ FROM coupons c
+ JOIN coupon_category cc
+ ON c.category = cc.name
+ JOIN coupon_categories2toolbox_pages cc2tp
+ ON cc.id = cc2tp.category ";
+
+ $params[] = 'c.active = true';
+ if ($_REQUEST['catid'] && ctype_digit($_REQUEST['catid'])) {
+ $params[] = "cc2tp.page = {$_REQUEST['catid']}";
+ }
+} else {
+ // Not using coupon category filters
+ $sql = "
+ SELECT c.*, c.title as header, cc.name as category,
+ date_part('epoch', c.edate) as expire
+ FROM coupons c
+ JOIN coupon_category cc
+ ON c.category = cc.name ";
+
+ $params[] = 'c.active = true';
+}
+if (!empty($params)) {
+ $sql .= "WHERE ". implode(" AND ", $params);
+}
+$sql .= " ORDER BY cc.name, c.sdate";
+/*
+echo '<pre>';
+var_dump($_REQUEST);
+var_dump($_POST);
+var_dump($sql);
+echo '</pre>';
+exit;
+ */
+try {
+ $res = $dbh->query($sql);
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $data[] = $row;
+ }
+} catch(PDOException $e) {
+ Toolkit_Common::handleError($e);
+}
+if (!is_array($data)) {
+ die('<p>'.$sql.'</p>');
+// header("Location: /index.php");
+}
+class Creport extends Cezpdf
+{
+ var $reportContents = array();
+
+ function Creport($p, $o)
+ {
+ $this->Cezpdf($p, $o);
+ }
+}
+
+$pdf = new Creport('a4', 'portrait');
+$pdf->selectFont(GLM_APP_BASE."coupons/fonts/Helvetica.afm");
+$pdf->ezSetMargins(90, 30, 30, 35);
+// put a line top and bottom on all the pages
+$all = $pdf->openObject();
+$pdf->saveState();
+$pdf->setLineStyle(1, '', '', array(20, 5, 10, 5));
+$pdf->setStrokeColor(0, 0, 0, 1);
+$pdf->addText(50, 34, 6, MEDIA_BASE_URL.date('F jS, Y'));
+$pdf->restoreState();
+$pdf->closeObject();
+// note that object can be told to appear on just odd or even pages by changing 'all' to 'odd'
+// or 'even'.
+$pdf->addObject($all, 'all');
+
+$coupon_lft_opt = array(
+ 'left' => 5,
+ 'right' => 280,
+ 'justification'=>'left'
+);
+$coupon_rgt_opt = array(
+ 'left' => 290,
+ 'justification'=>'left'
+);
+$minY = $y // y is verticle position starting at lower left hand corner
+ = 800;
+$x = 20; // x is horizontal position starting at lover left hand corner
+$coupon_width = 265; //
+$mycount = $count = 1; //
+foreach ($data as $key => $val) {
+ $reset = $y;
+ if (is_numeric($val['member'])) {
+ $query = "
+ SELECT member_name,street,city_name,state_abb,zip,phone
+ FROM member
+ LEFT OUTER JOIN city ON (city.city_id = member.city_id)
+ LEFT OUTER JOIN state ON (state.state_id = member.state_id)
+ WHERE member_id = {$val['member']}";
+ $memberData = $dbh->query($query)->fetch(PDO::FETCH_ASSOC);
+ if ($memberData) {
+ $member_name = htmlentities($memberData['member_name']);
+ }
+ $addressFormat = "%s\n%s, %s %s";
+ $memberAddress = sprintf(
+ $addressFormat,
+ $memberData['street'],
+ $memberData['city_name'],
+ $memberData['state_abb'],
+ $memberData['zip']
+ );
+ $phone = $memberData['phone'];
+ $header = "<b>".$member_name."</b>\n";
+ } else {
+ $memberAddress = '';
+ $phone = '';
+ $header = '';
+ }
+ $val['header'] = iconv('UTF-8', 'ISO-8859-1//IGNORE', $val['header']);
+ $val['description'] = iconv('UTF-8', 'ISO-8859-1//IGNORE', $val['description']);
+ $header .= "<b>".$val['header']."</b>\n";
+ $descr = preg_replace(
+ "/<br>|<br \/>/i",
+ "\n",
+ strip_tags(substr($val['description'], 0, 600))
+ )."\n";
+ $url = preg_replace('/http:\/\//i', '', $val['url']);
+ $expire = '<b>Expires: '.date("n/j/Y", $val["expire"]).'</b>';
+ if ($count == 2) {
+ $reset = $y;
+ $options = $coupon_rgt_opt;
+ $header_options = $options;
+ $header_options['justification'] = 'center';
+ $img_align = 'right';
+ } elseif ($count == 1) {
+ $options = $coupon_lft_opt;
+ $header_options = $options;
+ $header_options['justification'] = 'center';
+ $img_align = 'left';
+ }
+ $pdf->setLineStyle(1, '', '', array(5, 5, 5, 5));
+ $pdf->setColor(0, 0, 0, 1);
+ $pdf->setStrokeColor(0, 0, 0, 1);
+ $pdf->line($x, $y, $x + $coupon_width , $y); // make line for the top of coupon
+ $pdf->ezSetY($y);
+ $y = $pdf->ezText("\n".$header, 12, $header_options);
+ $y = $pdf->ezText($descr, 10, $options);
+ if ($memberAddress) {
+ $y = $pdf->ezText($memberAddress, 9, $header_options);
+ }
+ if ($phone) {
+ $y = $pdf->ezText($phone, 9, $header_options);
+ }
+ if ($url) {
+ $y = $pdf->ezText($url, 9, $header_options);
+ }
+ $y = $pdf->ezText("\n".$expire."\n", 9, $options);
+ // bottom footer
+ $pdf->saveState();
+ $pdf->setLineStyle(1, null, null, array());
+ $pdf->line($x, $y, $x + $coupon_width, $y); // make line for bottom
+ $y = $pdf->ezText( "<b>".SITENAME."</b> - <b>".COUPON_SITE_URL."</b>\n", 8, $options );
+ $pdf->restoreState();
+ $pdf->line($x, $y, $x + $coupon_width, $y); // make line for bottom
+ $pdf->line($x + $coupon_width, $reset, $x + $coupon_width, $y); // make right
+ $pdf->line($x, $reset, $x, $y); // make left
+ if ($count == 2 && $mycount != count($data)) {
+ $x = 20;
+ $count = 0;
+ if ($minY <= $y) {
+ $y = $minY - 5;
+ } else {
+ $y = $y - 5;
+ }
+ if ($y < 180 || ($mycount % 8 == 0)) {
+ $pdf->ezNewPage();
+ $y = 800;
+ $minY = $y;
+ }
+ } else {
+ $minY = $y;
+ $y = $reset;
+ $x = 300;
+ }
+ $count++;
+ $mycount++;
+}
+$output_options['Content-Disposition'] = "coupons.pdf";
+$pdfcode = $pdf->output();
+$dir = './pdf_files';
+// also have a look through the directory, and remove the files that are older than a day
+if ($d = @opendir($dir)) {
+ while (($file = readdir($d)) !== false) {
+ if (substr($file,0,4) == "PDF_"){
+ // then check to see if this one is too old
+ $ftime = filemtime($dir.'/'.$file);
+ if (time()-$ftime > 3600*24){
+ unlink($dir.'/'.$file);
+ }
+ }
+ }
+ closedir($d);
+}
+//save the file
+if (!file_exists($dir)) {
+ mkdir($dir, 0777);
+}
+$fname = tempnam($dir.'/', 'PDF_');
+unlink($fname);
+$fname .= '.pdf';
+$fp = fopen($fname, 'w');
+fwrite($fp, $pdfcode);
+fclose($fp);
+chmod($fname, 0666);
+header("Location: pdf_files/".basename($fname));
--- /dev/null
+<?php
+ include_once("../setup.phtml");
+ include_once("class.ezpdf.php");
+ extract($_POST);
+
+ $conn = db_connect();
+ foreach( $_POST as $pKey => $pVal )
+ {
+ if( preg_match( '/coupon_([0-9]*)/' ,$pKey, $coupon_part ) )
+ {
+ $coupon_arr[] = $coupon_part[1];
+ }
+ if( !$allcats )
+ {
+ $where_add = "and coupons.id in (".implode( ",",$coupon_arr ).") ";
+ }
+ }
+ if($coupons_catid == '')
+ {
+ $query = "SELECT coupons.*,coupons.title as header,cc.name as category
+ FROM coupons left outer join coupon_category cc on ( cc.id = coupons.catid )
+ WHERE coupons.edate > CURRENT_DATE
+ AND coupons.sdate <= CURRENT_DATE
+ $where_add
+ ORDER BY cc.name,coupons.sdate";
+ }
+ elseif( $where_add )
+ {
+ $query = "SELECT *
+ FROM coupons
+ WHERE edate > CURRENT_DATE
+ AND sdate <= CURRENT_DATE
+ and catid = $coupons_catid
+ $where_add
+ ORDER BY sdate";
+ }
+ else
+ {
+ // get all the coupons
+ $query = "SELECT coupons.*,coupons.title as header,cc.name as category
+ FROM coupons left outer join coupon_category cc on ( cc.id = coupons.catid )
+ WHERE coupons.edate > CURRENT_DATE
+ AND coupons.sdate <= CURRENT_DATE
+ and cc.id = $coupons_catid
+ $where_add
+ ORDER BY cc.name,coupons.sdate";
+ }
+ $result = pg_exec($conn, $query);
+ while($row = pg_fetch_array($result))
+ {
+ $data[] = $row;
+ }
+ if(!is_array($data))
+ {
+ header("Location: /index.php");
+ }
+ class Creport extends Cezpdf {
+ var $reportContents = array();
+ function Creport($p,$o){
+ $this->Cezpdf($p,$o);
+ }
+ }
+ function myAddImage(&$pdf,$image,$x,$y,$width,$height)
+ {
+ // this is the image magic convert binary
+ exec( "which convert", $output, $return );
+ $CONVERT = $output[0];
+ if($image != "" && is_file($image))
+ {
+ // find out if the image is a jpg or gif
+ if(preg_match("/\.gif$/i",$image))
+ {
+ // get the base name of file
+ $oldimage = $image;
+ $newimage = str_replace(THUMB_PATH,"",$image);
+ $newimage = str_replace(".gif",".jpg",$newimage);
+ exec("$CONVERT '$oldimage' '$newimage'");
+
+ $pdf->addJpegFromFile($newimage,$x,$y,$width,$height);
+ }
+ elseif(preg_match("/\.png$/i",$image))
+ {
+ // get the base name of file
+ $oldimage = $image;
+ $newimage = str_replace(THUMB_PATH,"",$image);
+ $newimage = str_replace(".png",".jpg",$newimage);
+ $newimage = BASE."temp/$newimage";
+ system("$CONVERT '$oldimage' '$newimage'",$return);
+ $pdf->addJpegFromFile($newimage,$x,$y,$width,$height);
+ }
+ elseif(preg_match("/\.jpe?g$/i",$image))
+ {
+ $pdf->addJpegFromFile($image,$x,$y,$width,$height);
+ }
+ }
+ }
+ $pdf = new Creport('a4','portrait');
+ $pdf->ezSetMargins(90,30,30,70);
+ // put a line top and bottom on all the pages
+ $all = $pdf->openObject();
+ $pdf->saveState();
+ $pdf->setLineStyle(1,'','',array(20,5,10,5));
+ $pdf->setStrokeColor(0,0,0,1);
+ $pdf->addText(50,34,6,'http://www.stignace.com '.date('F jS, Y'));
+ $pdf->restoreState();
+ $pdf->closeObject();
+ // note that object can be told to appear on just odd or even pages by changing 'all' to 'odd'
+ // or 'even'.
+ $pdf->addObject($all,'all');
+
+ $pdf->selectFont("./fonts/Helvetica.afm");
+ //$pdf->ezNewPage();
+ $pdf->setLineStyle(1,'','',array(10,10,10,10));
+ //$pdf->ezColumnsStart(array('num'=>2,'gap'=>3));
+ $coupon_lft_opt = array(
+ 'left' => 5,
+ 'right' => 265,
+ //'aleft' => 20,
+ 'justification'=>'center'
+ );
+ $coupon_rgt_opt = array(
+ 'left' => 320,
+ 'right' => 5,
+ //'aright' => 20,
+ 'justification'=>'center'
+ );
+ $y = 800;
+ $minY = $y;
+ $x = 20;
+ $count = 1;
+ $coupon_width = 265;
+ $mycount = 1;
+ foreach($data as $key=>$val)
+ {
+ $reset = $y;
+ $header = "<b>".$val['header']."</b>\n";
+ $descr = preg_replace("/<br>|<br \/>/i","\n",htmlentities(strip_tags($val['description'])));
+ $url = ($val['url'] != '') ? "\n<c:alink:http://".$val['url'].">http://".$val['url']."</c:alink>":'';
+ if($count == 2)
+ {
+ $reset = $y;
+ $options = $coupon_rgt_opt;
+ $img_align = 'right';
+ }
+ elseif( $count == 1 )
+ {
+ $options = $coupon_lft_opt;
+ $img_align = 'left';
+ }
+ $pdf->setLineStyle(1,'','',array(5,5,5,5));
+ $pdf->setColor(0,0,0,1);
+ $pdf->setStrokeColor(0,0,0,1);
+ $pdf->line( $x, $y, $x + $coupon_width , $y ); // make line for te top of coupon
+ $pdf->ezSetY($y);
+ $y = $pdf->ezText( "\n\n".$header."\n", 12, $options );
+ // since the ezImage function only put the image in center of pdf
+ if( is_file( THUMB_PATH.$val['image'] ) )
+ {
+ $img_size = getImageSize( THUMB_PATH.$val['image'] );
+ $newX = $x + 75;
+ $newY = $y - ( floor( $img_size[1] * .933 ) );
+ $y = $newY - 5;
+ $pdf->ezSetY( $y );
+ myAddImage( &$pdf, THUMB_PATH.$val['image'], $newX, $newY, floor( $img_size[0] * .93 ), NULL );
+ //$y = $pdf->ezImage( THUMB_PATH.$val['image'], '30', '116', 'none', $img_align );
+ }
+ $y = $pdf->ezText( $descr, 10, $options );
+ $pdf->setLineStyle(1,'','',0);
+ $y = $pdf->ezText( $url."\n\n", 10, $options );
+ $pdf->setLineStyle(1,'','',array(5,5,5,5));
+ $y = $y - 5;
+ $pdf->line( $x, $y, $x + $coupon_width, $y ); // make line for bottom
+ $pdf->line( $x + $coupon_width, $reset, $x + $coupon_width, $y ); // make right
+ $pdf->line( $x, $reset, $x, $y ); // make left
+ if( $count == 2 )
+ {
+ $x = 20;
+ $count = 0;
+ if( $minY <= $y )
+ {
+ $y = $minY - 5;
+ }
+ else
+ {
+ $y = $y - 5;
+ }
+ if( $y < 260 )
+ {
+ $pdf->ezNewPage();
+ $y = 800;
+ $minY = $y;
+ }
+ }
+ else
+ {
+ $minY = $y;
+ $y = $reset;
+ $x = 300;
+ }
+ //echo "y_value = $y for $mycount<br>";
+ $count++;
+ $mycount++;
+ }
+ $output_options['Content-Disposition'] = "SI_coupons.pdf";
+ $pdfcode = $pdf->output();
+ $dir = './pdf_files';
+ //save the file
+ if (!file_exists($dir))
+ {
+ mkdir ($dir,0777);
+ }
+ $fname = tempnam($dir.'/','PDF_');
+ unlink($fname);
+ $fname .= '.pdf';
+ $fp = fopen($fname,'w');
+ fwrite($fp,$pdfcode);
+ fclose($fp);
+ chmod($fname,0666);
+ // also have a look through the directory, and remove the files that are older than a day
+ if ($d = @opendir($dir)) {
+ while (($file = readdir($d)) !== false) {
+ if (substr($file,0,4)=="PDF_"){
+ // then check to see if this one is too old
+ $ftime = filemtime($dir.'/'.$file);
+ if (time()-$ftime > 3600*24){
+ unlink($dir.'/'.$file);
+ }
+ }
+ }
+ closedir($d);
+ }
+ header("Location: $fname");
+?>
--- /dev/null
+#form-warning-top {
+ color: #FF0000;
+ font-size: 14px;
+ font-weight: bold;
+ margin-bottom: 0.5em;
+ margin-top: 1em;
+}
+.required, .req {
+ color: #FF0000;
+}
+.group {
+ display: -moz-inline-box;
+ width: 100%;
+}
+.group td {
+ width: 324px;
+}
+.requiredNote {
+ text-align: center;
+}
+#contact {
+ margin: 10px;
+}
+#contact table {
+ background-color: #FFFFFF;
+ border: 1px solid #EEEEEE;
+ border-collapse: collapse;
+}
+#contact td {
+ border: 1px solid #EEEEEE;
+ border-collapse: collapse;
+ color: #000000;
+ font-family: arial, helvetica, sans-serif;
+ padding: 3px;
+ font-size: 12px;
+}
+.labelcell {
+ background-color: transparent;
+ padding-right: 10px;
+ padding-top: 3px;
+ text-align: right;
+ white-space: nowrap;
+ width: 140px;
+}
+.fieldcell {
+ padding-left: 4px;
+ width: 320px;
+}
+.fieldcell .text {
+ width: 90%;
+}
+#contact table.group {
+ font-size: 10px;
+ border: none;
+ padding-top: 4px;
+}
+#contact table.group td {
+ border: none;
+}
+#contact .hdr {
+ background-color: #999999;
+ border: 1px solid #666666;
+ font-weight: bold;
+}
+.paging {
+ text-align: center;
+ background-color: #F6F6F6;
+ border-color: #E86a10;
+ border-color: #296DC0;
+ border-style: solid;
+ border-width: 1px 0;
+ margin: 1.0em 0;
+ padding: 8px 0;
+ text-align: center;
+ width: 100%;
+ font-size: 12px;
+
+}
+.paging b {
+ border: 1px solid #b22c2c;
+ border: 1px solid #E86A10;
+ background: #FFF;
+ padding: 5px 7px;
+ margin: 0 5px;
+}
+.paging a {
+ background: #FFF;
+ border: 1px solid #CCC;
+ padding: 5px 7px;
+ text-decoration: none;
+ font-family: helvetica, times;
+ color: #000;
+ margin: 0 5px;
+}
+.paging a:hover {
+ border: 1px solid #999;
+ border: 1px solid #b22c2c;
+ border: 1px solid #E86A10;
+}
+#dataGrid {
+ margin: 10px auto;
+ border: 1px solid #296DC0;
+ width: 100%;
+ border-collapse: collapse;
+}
+#dataGrid thead th {
+ background: #296DC0;
+ border: 1px solid #1b4880;
+ color: #000;
+ font-weight: normal;
+}
+#dataGrid th a {
+ font-weight: bolder;
+ color: #000;
+ text-decoration: none;
+}
+#dataGrid th a:hover {
+ color: #E86A10;
+ text-decoration: underline;
+}
+#dataGrid tr {
+ border: 1px solid #296DC0;
+ border-collapse: collapse;
+}
+#dataGrid tbody tr td {
+ padding: 5px;
+}
+#dataGrid .editLink, #dataGrid .delLink,
+#dataGrid .mailLink, #dataGrid .dateLink,
+#dataGrid .posLink {
+ text-align: center;
+}
+img.status {
+ border: none;
+}
+.even {
+ background-color: #D9D9D9;
+}
+#gridSorter {
+ margin: 0 auto;
+ padding: 10px;
+ text-align: center;
+ border: 1px solid #296DC0;
+}
+#gridSorter table {
+ border: none;
+}
+#gridSorter td {
+ border: none;
+}
+.fieldcell textarea {
+ width: 90%;
+ height: 70px;
+}
--- /dev/null
+<flexy:include src="head.html" >
+{searchForm:h}
+{coupons:h}
--- /dev/null
+<a href="http://www.adobe.com/products/acrobat/readstep2.html" target="_blank">
+ <img src="baseurl/assets/get_adobe_reader.png"
+ alt="Acrobat Reader"
+ style="float: right; margin: 0 0 10px 10px; border: 0;">
+</a>
+<p>
+ You will need Adobe Acrobat Reader to view and print the documents
+ contained within this section. You can download the Reader for free at
+ <a href="http://www.adobe.com/products/acrobat/readstep2.html"
+ target="_blank">Adobe Online</a>.
+</p>
+<p>
+ Select the coupons you would like to print and click "Print Selected
+ Coupons" or "Print These Coupons" to select all.
+</p>
--- /dev/null
+<?php
+// vim:set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker syntax=php:
+
+/**
+ * Create Datagrids for displaying data
+ *
+ * PHP version 5
+ *
+ * @category Structures
+ * @package Toolkit_DataGridBuilder
+ * @author Jamie Kahgee <steve@gaslightmedia.com>
+ * @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 <steve@gaslightmedia.com>
+ * @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;
+ }
+ if ($_GET['page_id']) {
+ $this->pagerOptions['path'] = MEDIA_BASE_URL . 'members-only-area/';
+ }
+ }
+
+ // }}}
+
+ // {{{ 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 "<h2>{$this->noRecMessage}</h2>";
+ }
+ }
+
+ // }}}
+}
+?>
--- /dev/null
+<?php\r
+date_default_timezone_set('America/New_York');\r
+\r
+/**\r
+ * Class that is using REST to communicate with ConstantContact server\r
+ * This class currently supports actions performed using the contacts, lists, and campaigns APIs\r
+ * @author ConstantContact Dev Team\r
+ * @version 2.0.0\r
+ * @since 30.03.2010\r
+ */\r
+class CC_Utility\r
+{\r
+\r
+ // FROM HERE YOU MAY MODIFY YOUR CREDENTIALS\r
+ var $login = CONSTANT_CONTACT_LOGIN; //Username for your account\r
+ var $password = CONSTANT_CONTACT_PASSWORD; //Password for your account\r
+ var $apikey = CONSTANT_CONTACT_APIKEY; // API Key for your account.\r
+ // CONTACT LIST OPTIONS\r
+ var $contact_lists = array(); // Define which lists will be available for sign-up.\r
+ var $force_lists = false; // Set this to true to take away the ability for users to select and de-select lists\r
+ var $show_contact_lists = true; // Set this to false to hide the list name(s) on the sign-up form.\r
+ // NOTE - Contact Lists will only be hidden if force_lists is set to true. This is to prevent available checkboxes form being hidden.\r
+ // FORM OPT IN SOURCE - (Who is performing these actions?)\r
+ var $actionBy = 'ACTION_BY_CONTACT'; // Values: ACTION_BY_CUSTOMER or ACTION_BY_CONTACT\r
+ // ACTION_BY_CUSTOMER - Constant Contact Account holder. Used in internal applications.\r
+ // ACTION_BY_CONTACT - Action by Site visitor. Used in web site sign-up forms.\r
+ // DEBUGGING\r
+ var $curl_debug = true; // Set this to true to see the response code returned by cURL\r
+ // YOUR BASIC CHANGES SHOULD END HERE\r
+ var $requestLogin; //this contains full authentication string.\r
+ var $lastError = ''; // this variable will contain last error message (if any)\r
+ var $apiPath = 'https://api.constantcontact.com/ws/customers/'; //is used for server calls.\r
+ var $doNotIncludeLists = array('Removed', 'Do Not Mail', 'Active'); //define which lists shouldn't be returned.\r
+\r
+ public function __construct()\r
+ {\r
+ //when the object is getting initialized, the login string must be created as API_KEY%LOGIN:PASSWORD\r
+ $this->requestLogin = $this->apikey . "%" . $this->login . ":" . $this->password;\r
+ $this->apiPath = $this->apiPath . $this->login;\r
+\r
+ try {\r
+ if ($this->login == "username" || $this->password == "password"\r
+ || $this->apikey == "apikey") {\r
+ throw new Exception("You need to update your credentials in your cc_class.php");\r
+ }\r
+ } catch (Exception $e) {\r
+ echo "<strong>" . $e . "</strong>";\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Method that returns a list with all states found in states.txt file\r
+ * @return array with state codes and state names\r
+ */\r
+ public function getStates()\r
+ {\r
+ $returnArr = array();\r
+ $lines = file("states.txt");\r
+ foreach ($lines as $line) {\r
+ $tmp = explode(" - ", $line);\r
+ if (sizeof($tmp) == 2) {\r
+ $returnArr[trim($tmp[1])] = trim($tmp[0]);\r
+ }\r
+ }\r
+ return $returnArr;\r
+ }\r
+\r
+ /**\r
+ * Returns a list with all countries found in countries.txt file\r
+ * @return array with country codes and country names\r
+ */\r
+ public function getCountries()\r
+ {\r
+ $returnArr = array();\r
+ $lines = file("countries.txt");\r
+ foreach ($lines as $line) {\r
+ $tmp = explode(" - ", $line);\r
+ if (sizeof($tmp) == 2) {\r
+ $returnArr[trim($tmp[1])] = trim($tmp[0]);\r
+ }\r
+ }\r
+ return $returnArr;\r
+ }\r
+\r
+ /**\r
+ * Validate an email address\r
+ * @return TRUE if address is valid and FALSE if not.\r
+ */\r
+ protected function isValidEmail($email)\r
+ {\r
+ return preg_match('/^[_a-z0-9-][^()<>@,;:"[] ]*@([a-z0-9-]+.)+[a-z]{2,4}$/i', $email);\r
+ }\r
+\r
+ /**\r
+ * Private function used to send requests to ConstantContact server\r
+ * @param string $request - is the URL where the request will be made\r
+ * @param string $parameter - if it is not empty then this parameter will be sent using POST method\r
+ * @param string $type - GET/POST/PUT/DELETE\r
+ * @return a string containing server output/response\r
+ */\r
+ protected function doServerCall($request, $parameter = '', $type = "GET")\r
+ {\r
+ $ch = curl_init();\r
+ $request = str_replace('http://', 'https://', $request);\r
+ // Convert id URI to BASIC compliant\r
+ curl_setopt($ch, CURLOPT_URL, $request);\r
+ curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)");\r
+ curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);\r
+ curl_setopt($ch, CURLOPT_USERPWD, $this->requestLogin);\r
+ # curl_setopt ($ch, CURLOPT_FOLLOWLOCATION ,1);\r
+ curl_setopt($ch, CURLOPT_HEADER, 0);\r
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);\r
+ curl_setopt($ch, CURLOPT_HTTPHEADER, Array("Content-Type:application/atom+xml", 'Content-Length: ' . strlen($parameter)));\r
+ curl_setopt($ch, CURLOPT_FAILONERROR, 1);\r
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);\r
+ switch ($type) {\r
+ case 'POST':\r
+ curl_setopt($ch, CURLOPT_POST, 1);\r
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $parameter);\r
+ break;\r
+ case 'PUT':\r
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");\r
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $parameter);\r
+ break;\r
+ case 'DELETE':\r
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");\r
+ break;\r
+ default:\r
+ curl_setopt($ch, CURLOPT_HTTPGET, 1);\r
+ break;\r
+ }\r
+\r
+ $emessage = curl_exec($ch);\r
+ if ($this->curl_debug) {\r
+ echo $error = curl_error($ch);\r
+ }\r
+ curl_close($ch);\r
+\r
+ return $emessage;\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ * Class that is used for retrieving\r
+ * all the Email Lists from Constant Contact and\r
+ * all Registered Email Addresses\r
+ */\r
+class CC_List\r
+ extends CC_Utility\r
+{\r
+\r
+ /**\r
+ * Recursive Method that retrieves all the Email Lists from ConstantContact.\r
+ * @param string $path [default is empty]\r
+ * @return array of lists\r
+ */\r
+ public function getLists($path = '')\r
+ {\r
+ $mailLists = array();\r
+\r
+ if (empty($path)) {\r
+ $call = $this->apiPath . '/lists';\r
+ } else {\r
+ $call = $path;\r
+ }\r
+\r
+ $return = $this->doServerCall($call);\r
+ $parsedReturn = simplexml_load_string($return);\r
+ $call2 = '';\r
+\r
+ foreach ($parsedReturn->link as $item) {\r
+ $tmp = $item->Attributes();\r
+ $nextUrl = '';\r
+ if ((string) $tmp->rel == 'next') {\r
+ $nextUrl = (string) $tmp->href;\r
+ $arrTmp = explode($this->login, $nextUrl);\r
+ $nextUrl = $arrTmp[1];\r
+ $call2 = $this->apiPath . $nextUrl;\r
+ break;\r
+ }\r
+ }\r
+\r
+ foreach ($parsedReturn->entry as $item) {\r
+ if ($this->contact_lists) {\r
+ if (in_array((string) $item->title, $this->contact_lists)) {\r
+ $tmp = array();\r
+ $tmp['id'] = (string) $item->id;\r
+ $tmp['title'] = (string) $item->title;\r
+ $mailLists[] = $tmp;\r
+ }\r
+ } else if (!in_array((string) $item->title, $this->doNotIncludeLists)) {\r
+ $tmp = array();\r
+ $tmp['id'] = (string) $item->id;\r
+ $tmp['title'] = (string) $item->title;\r
+ $mailLists[] = $tmp;\r
+ }\r
+ }\r
+\r
+ if (empty($call2)) {\r
+ return $mailLists;\r
+ } else {\r
+ return array_merge($mailLists, $this->getLists($call2));\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Method that retrieves all Registered Email Addresses.\r
+ * @param string $email_id [default is empty]\r
+ * @return array of lists\r
+ */\r
+ public function getAccountLists($email_id = '')\r
+ {\r
+ $mailAccountList = array();\r
+\r
+ if (empty($email_id)) {\r
+ $call = $this->apiPath . '/settings/emailaddresses';\r
+ } else {\r
+ $call = $this->apiPath . '/settings/emailaddresses/' . $email_id;\r
+ }\r
+\r
+ $return = $this->doServerCall($call);\r
+ $parsedReturn = simplexml_load_string($return);\r
+\r
+ foreach ($parsedReturn->entry as $item) {\r
+ $nextStatus = $item->content->Email->Status;\r
+ $nextEmail = (string) $item->title;\r
+ $nextId = $item->id;\r
+ $nextAccountList = array('Email' => $nextEmail, 'Id' => $nextId);\r
+ if ($nextStatus == 'Verified') {\r
+ $mailAccountList[] = $nextAccountList;\r
+ }\r
+ }\r
+ return $mailAccountList;\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ * Class that is used for ConstantConact CRUD management\r
+ */\r
+class CC_Contact\r
+ extends CC_Utility\r
+{\r
+\r
+ /**\r
+ * Method that checks if a subscriber already exist\r
+ * @param string $email\r
+ * @return subscriber`s id if it exists or false if it doesn't\r
+ */\r
+ public function subscriberExists($email = '')\r
+ {\r
+ $call = $this->apiPath . '/contacts?email=' . $email;\r
+ $return = $this->doServerCall($call);\r
+ $xml = simplexml_load_string($return);\r
+ $id = $xml->entry->id;\r
+ if ($id) {\r
+ return $id;\r
+ } else {\r
+ return false;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Method that retrieves from Constant Contact a collection with all the Subscribers\r
+ * If email parameter is mentioned then only mentioned contact is retrieved.\r
+ * @param string $email\r
+ * @return Bi-Dimenstional array with information about contacts.\r
+ */\r
+ public function getSubscribers($email = '', $page = '')\r
+ {\r
+ $contacts = array();\r
+ $contacts['items'] = array();\r
+\r
+ if (!empty($email)) {\r
+ $call = $this->apiPath . '/contacts?email=' . $email;\r
+ } else {\r
+ if (!empty($page)) {\r
+ $call = $this->apiPath . $page;\r
+ } else {\r
+ $call = $this->apiPath . '/contacts';\r
+ }\r
+ }\r
+\r
+ $return = $this->doServerCall($call);\r
+ $parsedReturn = simplexml_load_string($return);\r
+ // We parse here the link array to establish which are the next page and previous page\r
+ foreach ($parsedReturn->link as $item) {\r
+ $attributes = $item->Attributes();\r
+\r
+ if (!empty($attributes['rel']) && $attributes['rel'] == 'next') {\r
+ $tmp = explode($this->login, $attributes['href']);\r
+ $contacts['next'] = $tmp[1];\r
+ }\r
+ if (!empty($attributes['rel']) && $attributes['rel'] == 'first') {\r
+ $tmp = explode($this->login, $attributes['href']);\r
+ $contacts['first'] = $tmp[1];\r
+ }\r
+ if (!empty($attributes['rel']) && $attributes['rel'] == 'current') {\r
+ $tmp = explode($this->login, $attributes['href']);\r
+ $contacts['current'] = $tmp[1];\r
+ }\r
+ }\r
+\r
+ foreach ($parsedReturn->entry as $item) {\r
+ $tmp = array();\r
+ $tmp['id'] = (string) $item->id;\r
+ $tmp['title'] = (string) $item->title;\r
+ $tmp['status'] = (string) $item->content->Contact->Status;\r
+ $tmp['EmailAddress'] = (string) $item->content->Contact->EmailAddress;\r
+ $tmp['EmailType'] = (string) $item->content->Contact->EmailType;\r
+ $tmp['Name'] = (string) $item->content->Contact->Name;\r
+ $contacts['items'][] = $tmp;\r
+ }\r
+\r
+ return $contacts;\r
+ }\r
+\r
+ /**\r
+ * Retrieves all the details for a specific contact identified by $email.\r
+ * @param string $email\r
+ * @return array with all information about the contact.\r
+ */\r
+ public function getSubscriberDetails($email)\r
+ {\r
+ $contact = $this->getSubscribers($email);\r
+ $fullContact = array();\r
+ $call = str_replace('http://', 'https://', $contact['items'][0]['id']);\r
+ // Convert id URI to BASIC compliant\r
+ $return = $this->doServerCall($call);\r
+ $parsedReturn = simplexml_load_string($return);\r
+ $fullContact['id'] = $parsedReturn->id;\r
+ $fullContact['email_address'] = $parsedReturn->content->Contact->EmailAddress;\r
+ $fullContact['first_name'] = $parsedReturn->content->Contact->FirstName;\r
+ $fullContact['last_name'] = $parsedReturn->content->Contact->LastName;\r
+ $fullContact['middle_name'] = $parsedReturn->content->Contact->MiddleName;\r
+ $fullContact['company_name'] = $parsedReturn->content->Contact->CompanyName;\r
+ $fullContact['job_title'] = $parsedReturn->content->Contact->JobTitle;\r
+ $fullContact['home_number'] = $parsedReturn->content->Contact->HomePhone;\r
+ $fullContact['work_number'] = $parsedReturn->content->Contact->WorkPhone;\r
+ $fullContact['address_line_1'] = $parsedReturn->content->Contact->Addr1;\r
+ $fullContact['address_line_2'] = $parsedReturn->content->Contact->Addr2;\r
+ $fullContact['address_line_3'] = $parsedReturn->content->Contact->Addr3;\r
+ $fullContact['city_name'] = (string) $parsedReturn->content->Contact->City;\r
+ $fullContact['state_code'] = (string) $parsedReturn->content->Contact->StateCode;\r
+ $fullContact['state_name'] = (string) $parsedReturn->content->Contact->StateName;\r
+ $fullContact['country_code'] = $parsedReturn->content->Contact->CountryCode;\r
+ $fullContact['zip_code'] = $parsedReturn->content->Contact->PostalCode;\r
+ $fullContact['sub_zip_code'] = $parsedReturn->content->Contact->SubPostalCode;\r
+ $fullContact['custom_field_1'] = $parsedReturn->content->Contact->CustomField1;\r
+ $fullContact['custom_field_2'] = $parsedReturn->content->Contact->CustomField2;\r
+ $fullContact['custom_field_3'] = $parsedReturn->content->Contact->CustomField3;\r
+ $fullContact['custom_field_4'] = $parsedReturn->content->Contact->CustomField4;\r
+ $fullContact['custom_field_5'] = $parsedReturn->content->Contact->CustomField5;\r
+ $fullContact['custom_field_6'] = $parsedReturn->content->Contact->CustomField6;\r
+ $fullContact['custom_field_7'] = $parsedReturn->content->Contact->CustomField7;\r
+ $fullContact['custom_field_8'] = $parsedReturn->content->Contact->CustomField8;\r
+ $fullContact['custom_field_9'] = $parsedReturn->content->Contact->CustomField9;\r
+ $fullContact['custom_field_10'] = $parsedReturn->content->Contact->CustomField10;\r
+ $fullContact['custom_field_11'] = $parsedReturn->content->Contact->CustomField11;\r
+ $fullContact['custom_field_12'] = $parsedReturn->content->Contact->CustomField12;\r
+ $fullContact['custom_field_13'] = $parsedReturn->content->Contact->CustomField13;\r
+ $fullContact['custom_field_14'] = $parsedReturn->content->Contact->CustomField14;\r
+ $fullContact['custom_field_15'] = $parsedReturn->content->Contact->CustomField15;\r
+ $fullContact['notes'] = $parsedReturn->content->Contact->Note;\r
+ $fullContact['mail_type'] = $parsedReturn->content->Contact->EmailType;\r
+ $fullContact['status'] = $parsedReturn->content->Contact->Status;\r
+ $fullContact['lists'] = array();\r
+\r
+ if ($parsedReturn->content->Contact->ContactLists->ContactList) {\r
+ foreach ($parsedReturn->content->Contact->ContactLists->ContactList as $item) {\r
+ $fullContact['lists'][] = trim((string) $item->Attributes());\r
+ }\r
+ }\r
+\r
+ return $fullContact;\r
+ }\r
+\r
+ /**\r
+ * Method that modifies a contact State to DO NOT MAIL\r
+ * @param string $email - contact email address\r
+ * @return TRUE in case of success or FALSE otherwise\r
+ */\r
+ public function deleteSubscriber($email)\r
+ {\r
+ if (empty($email)) {\r
+ return false;\r
+ }\r
+ $contact = $this->getSubscribers($email);\r
+ $id = $contact['items'][0]['id'];\r
+ $return = $this->doServerCall($id, '', 'DELETE');\r
+ if (!empty($return)) {\r
+ return false;\r
+ }\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * Method that modifies a contact State to REMOVED\r
+ * @param string $email - contact email address\r
+ * @return TRUE in case of success or FALSE otherwise\r
+ */\r
+ public function removeSubscriber($email)\r
+ {\r
+ $contact = $this->getSubscriberDetails($email);\r
+ $contact['lists'] = array();\r
+ $xml = $this->createContactXML($contact['id'], $contact);\r
+\r
+ if ($this->editSubscriber($contact['id'], $xml)) {\r
+ return true;\r
+ } else {\r
+ return false;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Upload a new contact to Constant Contact server\r
+ * @param strong $contactXML - formatted XML with contact information\r
+ * @return TRUE in case of success or FALSE otherwise\r
+ */\r
+ public function addSubscriber($contactXML)\r
+ {\r
+ $call = $this->apiPath . '/contacts';\r
+ $return = $this->doServerCall($call, $contactXML, 'POST');\r
+ $parsedReturn = simplexml_load_string($return);\r
+\r
+ if ($return) {\r
+ return true;\r
+ } else {\r
+ $xml = simplexml_load_string($contactXML);\r
+ $emailAddress = $xml->content->Contact->EmailAddress;\r
+ if ($this->subscriberExists($emailAddress)) {\r
+ $this->lastError = 'This contact already exists. <a href="edit_contact.php?email=' . $emailAddress . '">Click here</a> to edit the contact details.';\r
+ } else {\r
+ $this->lastError = 'An Error Occurred';\r
+ }\r
+ return false;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Modifies a contact\r
+ * @param string $contactUrl - identifies the url for the modified contact\r
+ * @param string $contactXML - formed XML with contact information\r
+ * @return TRUE in case of success or FALSE otherwise\r
+ */\r
+ public function editSubscriber($contactUrl, $contactXML)\r
+ {\r
+ $return = $this->doServerCall($contactUrl, $contactXML, 'PUT');\r
+\r
+ if (!empty($return)) {\r
+ if (strpos($return, '<') !== false) {\r
+ $parsedReturn = simplexml_load_string($return);\r
+ if (!empty($parsedReturn->message)) {\r
+ $this->lastError = $parsedReturn->message;\r
+ }\r
+ } else {\r
+ $this->lastError = $parsedReturn->message;\r
+ }\r
+ return false;\r
+ }\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * Method that compose the needed XML format for a contact\r
+ * @param string $id\r
+ * @param array $params\r
+ * @return Formed XML\r
+ */\r
+ public function createContactXML($id, $params = array())\r
+ {\r
+ if (empty($id)) {\r
+ $id = "urn:uuid:E8553C09F4xcvxCCC53F481214230867087";\r
+ }\r
+\r
+ $update_date = date("Y-m-d") . 'T' . date("H:i:s") . '+01:00';\r
+ $xml_string = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><entry xmlns='http://www.w3.org/2005/Atom'></entry>";\r
+ $xml_object = simplexml_load_string($xml_string);\r
+ $title_node = $xml_object->addChild("title", htmlspecialchars(("TitleNode"), ENT_QUOTES, 'UTF-8'));\r
+ $updated_node = $xml_object->addChild("updated", htmlspecialchars(($update_date), ENT_QUOTES, 'UTF-8'));\r
+ $author_node = $xml_object->addChild("author");\r
+ $author_name = $author_node->addChild("name", ("CTCT Samples"));\r
+ $id_node = $xml_object->addChild("id", htmlspecialchars(($id), ENT_QUOTES, 'UTF-8'));\r
+ $summary_node = $xml_object->addChild("summary", htmlspecialchars(("Customer document"), ENT_QUOTES, 'UTF-8'));\r
+ $summary_node->addAttribute("type", "text");\r
+ $content_node = $xml_object->addChild("content");\r
+ $content_node->addAttribute("type", "application/vnd.ctct+xml");\r
+ $contact_node = $content_node->addChild("Contact", htmlspecialchars(("Customer document"), ENT_QUOTES, 'UTF-8'));\r
+ $contact_node->addAttribute("xmlns", "http://ws.constantcontact.com/ns/1.0/");\r
+ $email_node = $contact_node->addChild("EmailAddress", htmlspecialchars(($params['email_address']), ENT_QUOTES, 'UTF-8'));\r
+ $fname_node = $contact_node->addChild("FirstName", urldecode(htmlspecialchars(($params['first_name']), ENT_QUOTES, 'UTF-8')));\r
+ $lname_node = $contact_node->addChild("LastName", urldecode(htmlspecialchars(($params['last_name']), ENT_QUOTES, 'UTF-8')));\r
+ $lname_node = $contact_node->addChild("MiddleName", urldecode(htmlspecialchars(($params['middle_name']), ENT_QUOTES, 'UTF-8')));\r
+ if (isset($params['company_name'])) {\r
+ $lname_node = $contact_node->addChild("CompanyName", urldecode(htmlspecialchars(($params['company_name']), ENT_QUOTES, 'UTF-8')));\r
+ }\r
+ if (isset($params['JobTitle'])) {\r
+ $lname_node = $contact_node->addChild("job_title", urldecode(htmlspecialchars(($params['job_title']), ENT_QUOTES, 'UTF-8')));\r
+ }\r
+ if (isset($params['status'])) {\r
+ if ($params['status'] == 'Do Not Mail') {\r
+ $this->actionBy = 'ACTION_BY_CONTACT';\r
+ }\r
+ }\r
+\r
+ $optin_node = $contact_node->addChild("OptInSource", htmlspecialchars($this->actionBy));\r
+ $hn_node = $contact_node->addChild("HomePhone", htmlspecialchars($params['home_number'], ENT_QUOTES, 'UTF-8'));\r
+ if (isset($params['work_number'])) {\r
+ $wn_node = $contact_node->addChild("WorkPhone", htmlspecialchars($params['work_number'], ENT_QUOTES, 'UTF-8'));\r
+ }\r
+ $ad1_node = $contact_node->addChild("Addr1", htmlspecialchars($params['address_line_1'], ENT_QUOTES, 'UTF-8'));\r
+ $ad2_node = $contact_node->addChild("Addr2", htmlspecialchars($params['address_line_2'], ENT_QUOTES, 'UTF-8'));\r
+ $ad3_node = $contact_node->addChild("Addr3", htmlspecialchars($params['address_line_3'], ENT_QUOTES, 'UTF-8'));\r
+ $city_node = $contact_node->addChild("City", htmlspecialchars($params['city_name'], ENT_QUOTES, 'UTF-8'));\r
+ $state_node = $contact_node->addChild("StateCode", htmlspecialchars($params['state_code'], ENT_QUOTES, 'UTF-8'));\r
+ $state_name = $contact_node->addChild("StateName", htmlspecialchars($params['state_name'], ENT_QUOTES, 'UTF-8'));\r
+ $ctry_node = $contact_node->addChild("CountryCode", htmlspecialchars($params['country_code'], ENT_QUOTES, 'UTF-8'));\r
+ $zip_node = $contact_node->addChild("PostalCode", htmlspecialchars($params['zip_code'], ENT_QUOTES, 'UTF-8'));\r
+ $subzip_node = $contact_node->addChild("SubPostalCode", htmlspecialchars($params['sub_zip_code'], ENT_QUOTES, 'UTF-8'));\r
+ if (isset($params['notes'])) {\r
+ $note_node = $contact_node->addChild("Note", htmlspecialchars($params['notes'], ENT_QUOTES, 'UTF-8'));\r
+ }\r
+ $emailtype_node = $contact_node->addChild("EmailType", htmlspecialchars($params['mail_type'], ENT_QUOTES, 'UTF-8'));\r
+\r
+ if (!empty($params['custom_fields'])) {\r
+ foreach ($params['custom_fields'] as $k => $v) {\r
+ $contact_node->addChild("CustomField" . $k, htmlspecialchars(($v), ENT_QUOTES, 'UTF-8'));\r
+ }\r
+ }\r
+\r
+ $contactlists_node = $contact_node->addChild("ContactLists");\r
+ if ($params['lists']) {\r
+ foreach ($params['lists'] as $tmp) {\r
+ $contactlist_node = $contactlists_node->addChild("ContactList");\r
+ $contactlist_node->addAttribute("id", $tmp);\r
+ }\r
+ }\r
+\r
+ $entry = $xml_object->asXML();\r
+ return $entry;\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ * Class that is used for ConstantCampaign CRUD management\r
+ */\r
+class CC_Campaign\r
+ extends CC_Utility\r
+{\r
+\r
+ // set this to true to see the xml sent and the output received\r
+ var $sent_recived_debug = false;\r
+ var $usStates = array("AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "DC", "FL", "GA", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "NM", "NY", "NC", "ND", "OH", "OK", "OR", "PA", "RI", "SC", "SD", "TN", "TX", "UT", "VT", "VA", "WA", "WV", "WI", "WY");\r
+ var $caStates = array("AB", "BC", "MB", "NB", "NL", "NT", "NS", "NU", "ON", "PE", "QC", "SK", "YT");\r
+ var $armedForces = array("AA", "AE", "AP");\r
+\r
+ /**\r
+ * Method that returns a html sample for email campaign\r
+ * @param string $sample [default is EmailContent]: EmailContent, EmailTextContent or\r
+ * PermissionReminder\r
+ * @param string $type [default is html]: html or text\r
+ * @return a default content for email content or permission reminder\r
+ */\r
+ public function getEmailIntro($sample = 'EmailContent', $type = 'html')\r
+ {\r
+ switch ($sample) {\r
+ case 'EmailContent':\r
+ $file = 'EmailContent.txt';\r
+ break;\r
+ case 'EmailTextContent':\r
+ $file = 'EmailContent.txt';\r
+ $type = 'text';\r
+ break;\r
+ case 'PermissionReminder':\r
+ $file = 'PermissionReminder.txt';\r
+ break;\r
+ default:\r
+ $file = 'EmailContent.txt';\r
+ }\r
+\r
+ $handle = fopen("txt/$file", "rb");\r
+ $contents = '';\r
+ while (!feof($handle)) {\r
+ $contents .= fread($handle, 8192);\r
+ }\r
+ $contents = ($type == 'html')\r
+ ? ($contents)\r
+ : (trim(strip_tags($contents)));\r
+ fclose($handle);\r
+ return $contents;\r
+ }\r
+\r
+ /**\r
+ * Method that retrieves campaingn collections from ConstantCampaign\r
+ * If campaign_id is mentioned then only mentioned campaign is retrieved.\r
+ * If campaign_id represents a status [SENT, DRAFT, RUNNING, SCHEDULED]\r
+ * only the campaigns with that status will be retrieved\r
+ * @param string $campaign_id [default is empty]\r
+ * @return Bi-Dimenstional array with information about campaigns.\r
+ */\r
+ public function getCampaigns($campaign_id = '', $page = '')\r
+ {\r
+ $campaigns = array();\r
+ $campaigns['items'] = array();\r
+\r
+ switch ($campaign_id) {\r
+ case 'SENT':\r
+ case 'DRAFT':\r
+ case 'RUNNING':\r
+ case 'SCHEDULED':\r
+ $call = $this->apiPath . '/campaigns?status=' . $campaign_id;\r
+ break;\r
+ case 'ALL':\r
+ $call = (!empty($page))\r
+ ? ($this->apiPath . $page)\r
+ : ($this->apiPath . '/campaigns');\r
+ break;\r
+ default:\r
+ $call = $this->apiPath . '/campaigns/' . $campaign_id;\r
+ }\r
+\r
+ $return = $this->doServerCall($call);\r
+ $parsedReturn = simplexml_load_string($return);\r
+ //we parse here the link array to establish which are the next page and previous page\r
+ if ($parsedReturn != false) {\r
+\r
+ foreach ($parsedReturn->link as $item) {\r
+ $attributes = $item->Attributes();\r
+ if (!empty($attributes['rel']) && $attributes['rel'] == 'next') {\r
+ $tmp = explode($this->login, $attributes['href']);\r
+ $campaigns['next'] = $tmp[1];\r
+ }\r
+ if (!empty($attributes['rel']) && $attributes['rel'] == 'first') {\r
+ $tmp = explode($this->login, $attributes['href']);\r
+ $campaigns['first'] = $tmp[1];\r
+ }\r
+ if (!empty($attributes['rel']) && $attributes['rel'] == 'current') {\r
+ $tmp = explode($this->login, $attributes['href']);\r
+ $campaigns['current'] = $tmp[1];\r
+ }\r
+ }\r
+\r
+ foreach ($parsedReturn->entry as $item) {\r
+ $tmp = array();\r
+ $tmp['id'] = (string) $item->id;\r
+ $tmp['title'] = (string) $item->title;\r
+ $tmp['name'] = (string) $item->content->Campaign->Name;\r
+ $tmp['status'] = (string) $item->content->Campaign->Status;\r
+ $timestamp = strtotime($item->content->Campaign->Date);\r
+ $campaig_date = date("F j, Y, g:i a", $timestamp);\r
+ $tmp['date'] = (string) $campaig_date;\r
+ $campaigns['items'][] = $tmp;\r
+ }\r
+ }\r
+ return $campaigns;\r
+ }\r
+\r
+ /**\r
+ * Retrieves all the details for a specific campaign identified by $id.\r
+ * @param string $id\r
+ * @return array with all information about the campaign.\r
+ */\r
+ public function getCampaignDetails($id)\r
+ {\r
+ if (!empty($id)) {\r
+ $fullContact = array();\r
+ $call = str_replace('http://', 'https://', $id);\r
+ // Convert id URI to BASIC compliant\r
+ $return = $this->doServerCall($call);\r
+ $parsedReturn = simplexml_load_string($return);\r
+ $fullCampaign['campaignId'] = $parsedReturn->id;\r
+ $cmp_vars = get_object_vars($parsedReturn->content->Campaign);\r
+\r
+ foreach ($cmp_vars as $var_name => $cmp_item) {\r
+ $fullCampaign[$var_name] = $cmp_item;\r
+ }\r
+\r
+ $cmp_from_email = $parsedReturn->content->Campaign->FromEmail->EmailAddress;\r
+ $fullCampaign['FromEmail'] = (string) $cmp_from_email;\r
+ $cmp_reply_email = $parsedReturn->content->Campaign->ReplyToEmail->EmailAddress;\r
+ $fullCampaign['ReplyToEmail'] = (string) $cmp_reply_email;\r
+ $fullCampaign['lists'] = array();\r
+\r
+ if ($parsedReturn->content->Campaign->ContactLists->ContactList) {\r
+ foreach ($parsedReturn->content->Campaign->ContactLists->ContactList as $item) {\r
+ $fullCampaign['lists'][] = trim((string) $item->Attributes());\r
+ }\r
+ }\r
+ return $fullCampaign;\r
+ } else {\r
+ return false;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Check if a specific campaign exist already\r
+ * @param string $id\r
+ * @param string $new_name\r
+ * @return a boolean value.\r
+ */\r
+ public function campaignExists($id = '', $new_name)\r
+ {\r
+ if (!empty($id)) {\r
+ $call = $this->apiPath . '/campaigns/' . $id;\r
+ $return = $this->doServerCall($call);\r
+ $xml = simplexml_load_string($return);\r
+ if ($xml !== false) {\r
+ $id = $xml->content->Campaign->Attributes();\r
+ $id = $id['id'];\r
+ $name = $xml->content->Campaign->Name;\r
+ } else {\r
+ $id = null;\r
+ $name = null;\r
+ }\r
+ $all_campaigns = $this->getCampaigns('ALL');\r
+ $all_campaigns = $all_campaigns['items'];\r
+ foreach ($all_campaigns as $key => $item) {\r
+ if ($item['name'] == $new_name) {\r
+ return 1; // 1 - the new campaign has a similar name with an old one\r
+ break;\r
+ }\r
+ }\r
+ /**\r
+ * 2 - this campaign already exist\r
+ * 0 - this is a new campaign\r
+ */\r
+ return ($id != null)\r
+ ? (2)\r
+ : (0);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Method that delete a camaign; this will exclude\r
+ * the removed campaign from overall statistics\r
+ * @param string $id - campaign id\r
+ * @return TRUE in case of success or FALSE otherwise\r
+ */\r
+ public function deleteCampaign($id)\r
+ {\r
+ if (empty($id)) {\r
+ return false;\r
+ }\r
+ $return = $this->doServerCall($id, '', 'DELETE');\r
+ if (!empty($return) || $return === false) {\r
+ return false;\r
+ }\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * Upload a new campaign to ConstantContact server\r
+ * @param string $campaignXML - formatted XML with campaign information\r
+ * @return TRUE in case of success or FALSE otherwise\r
+ */\r
+ public function addCampaign($campaignXML)\r
+ {\r
+ $call = $this->apiPath . '/campaigns';\r
+ $return = $this->doServerCall($call, $campaignXML, 'POST');\r
+ $parsedReturn = simplexml_load_string($return);\r
+ if ($return) {\r
+ return true;\r
+ } else {\r
+ $xml = simplexml_load_string($campaignXML);\r
+ $cmp_id = $xml->content->Campaign->Attributes();\r
+ $cmp_id = $cmp_id['id'];\r
+ $cmp_name = $xml->content->Campaign->Name;\r
+ if (!empty($cmp_id)) {\r
+ $search_status = $this->campaignExists($cmp_id, $cmp_name);\r
+ switch ($search_status) {\r
+ case 0:\r
+ $error = 'An Error Occurred. The campaign could not be added.';\r
+ break;\r
+ case 1:\r
+ $error = 'The name of the campaign already exist. Each campaign must have a distinct name.';\r
+ break;\r
+ case 2:\r
+ $error = 'This campaign already exists.';\r
+ break;\r
+ default:\r
+ $error = 'An Error Occurred. The campaign could not be added.';\r
+ }\r
+ $this->lastError = $error;\r
+ } else {\r
+ $this->lastError = 'An Error Occurred. The campaign could not be added.';\r
+ }\r
+ return false;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Modifies a campaign\r
+ * @param string $campaignId - identifies the id for the modified campaign\r
+ * @param string $campaignXML - formed XML with campaign information\r
+ * @return TRUE in case of success or FALSE otherwise\r
+ */\r
+ public function editCampaign($campaignId, $campaignXML)\r
+ {\r
+ $return = $this->doServerCall($campaignId, $campaignXML, 'PUT');\r
+ if ($return === false) {\r
+ $this->lastError = 'An Error Occurred. The campaign could not be edited.';\r
+ return false;\r
+ } else {\r
+ if (!empty($return)) {\r
+ if (strpos($return, '<') !== false) {\r
+ $parsedReturn = simplexml_load_string($return);\r
+ if (!empty($parsedReturn->message)) {\r
+ $this->lastError = $parsedReturn->message;\r
+ }\r
+ } else {\r
+ $this->lastError = $parsedReturn->message;\r
+ }\r
+ return false;\r
+ }\r
+ return true;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Method that validate the current campaign before sending it to server\r
+ * @param string $id\r
+ * @param array $params\r
+ * @return an error message or true\r
+ */\r
+ public function validateCampaign($id, $params = array())\r
+ {\r
+ if (trim($params['cmp_name']) == '') {\r
+ $this->lastError = '<i>Campaign Name</i> is mandatory.';\r
+ return true;\r
+ } elseif (trim($params['cmp_subject']) == '') {\r
+ $this->lastError = '<i>Subject</i> is mandatory.';\r
+ return true;\r
+ } elseif (trim($params['cmp_from_name']) == '') {\r
+ $this->lastError = '<i>From Name</i> is mandatory.';\r
+ return true;\r
+ } elseif (trim($params['cmp_from_email']) == '') {\r
+ $this->lastError = '<i>From Email Address</i> is mandatory.';\r
+ return true;\r
+ } elseif (trim($params['cmp_reply_email']) == '') {\r
+ $this->lastError = '<i>Reply Email Address</i> is mandatory.';\r
+ return true;\r
+ } elseif (trim($params['cmp_grt_name']) == '') {\r
+ $this->lastError = '<i>Greeting Name</i> is mandatory.';\r
+ return true;\r
+ } elseif (trim($params['cmp_org_name']) == '') {\r
+ $this->lastError = '<i>Organization Name</i> is mandatory.';\r
+ return true;\r
+ } elseif (trim($params['cmp_org_addr1']) == '') {\r
+ $this->lastError = '<i>Address 1</i> is mandatory.';\r
+ return true;\r
+ } elseif (trim($params['cmp_org_city']) == '') {\r
+ $this->lastError = '<i>City</i> is mandatory.';\r
+ return true;\r
+ } elseif (trim($params['org_zip']) == '') {\r
+ $this->lastError = '<i>Zip/Postal Code</i> is mandatory.';\r
+ return true;\r
+ } elseif (trim($params['org_country']) == '') {\r
+ $this->lastError = '<i>Country</i> is mandatory.';\r
+ return true;\r
+ } elseif (trim($params['cmp_html_body']) == '') {\r
+ $this->lastError = '<i>HTML Body</i> is mandatory.';\r
+ return true;\r
+ } elseif ($params["lists"] == NULL) {\r
+ $this->lastError = 'Choose at least <i>one Campaign</i> from the list.';\r
+ return true;\r
+ } else {\r
+ if (trim($params['cmp_perm_reminder']) == 'YES') {\r
+ $reminder_text = $params['cmp_txt_reminder'];\r
+ if (trim($reminder_text) == '') {\r
+ $this->lastError = '<i>Permission Reminder</i> is required.';\r
+ return true;\r
+ }\r
+ }\r
+ if (trim($params['org_country']) != '') {\r
+ if (trim($params['org_country']) == 'us') {\r
+ if (trim($params['org_state_us']) == '') {\r
+ $this->lastError = '<i>State</i> is mandatory.';\r
+ return true;\r
+ }\r
+ if (in_array($params['org_state_us'], $this->caStates)) {\r
+ $this->lastError = '<i>US State</i> is required.';\r
+ return true;\r
+ }\r
+ } elseif (trim($params['org_country']) == 'ca') {\r
+ if (trim($params['org_state_us']) == '') {\r
+ $this->lastError = '<i>State</i> is mandatory.';\r
+ return true;\r
+ }\r
+ if (in_array($params['org_state_us'], $this->usStates)) {\r
+ $this->lastError = '<i>CA State</i> is required.';\r
+ return true;\r
+ }\r
+ }\r
+ }\r
+ if (trim($params['cmp_as_webpage']) == 'YES') {\r
+ if (trim($params['cmp_as_webtxt']) == '') {\r
+ $this->lastError = '<i>Webpage Text</i> is required.';\r
+ return true;\r
+ }\r
+ if (trim($params['cmp_as_weblink']) == '') {\r
+ $this->lastError = '<i>Webpage Link Text</i> is required.';\r
+ return true;\r
+ }\r
+ }\r
+ if (trim($params['cmp_forward']) == 'YES') {\r
+ $fwd_email = $params['cmp_fwd_email'];\r
+ if (trim($params['cmp_fwd_email']) == '') {\r
+ $this->lastError = '<i>Forward email</i> is required.';\r
+ return true;\r
+ }\r
+ }\r
+ if (trim($params['cmp_subscribe']) == 'YES') {\r
+ if (trim($params['cmp_sub_link']) == '') {\r
+ $this->lastError = '<i>Subscribe me</i> is required.';\r
+ return true;\r
+ }\r
+ } else {\r
+ return false;\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Method that compose the needed XML format for a campaign\r
+ * @param string $id\r
+ * @param array $params\r
+ * @return Formed XML\r
+ */\r
+ public function createCampaignXML($id, $params = array())\r
+ {\r
+ if (empty($id)) { // Add a new Campaign\r
+ $id = str_replace('https://', 'http://', $this->apiPath . "/campaigns/1100546096289");\r
+ $standard_id = str_replace('https://', 'http://', $this->apiPath . "/campaigns");\r
+ } else {\r
+ $standard_id = $id;\r
+ }\r
+ $href = str_replace("http://api.constantcontact.com", "", $id);\r
+ $standard_href = str_replace("https://api.constantcontact.com", "", $this->apiPath . "/campaigns");\r
+ $update_date = date("Y-m-d") . 'T' . date("H:i:s") . '+01:00';\r
+ $xml_string = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><entry xmlns='http://www.w3.org/2005/Atom'></entry>";\r
+ $xml_object = simplexml_load_string($xml_string);\r
+ $link_node = $xml_object->addChild("link");\r
+ $link_node->addAttribute("href", $standard_href); //[1st *href]\r
+ $link_node->addAttribute("rel", "edit");\r
+ $id_node = $xml_object->addChild("id", $standard_id); //[1st *id]\r
+ $title_node = $xml_object->addChild("title", htmlspecialchars($params['cmp_name'], ENT_QUOTES, 'UTF-8'));\r
+ $title_node->addAttribute("type", "text");\r
+ $updated_node = $xml_object->addChild("updated", htmlentities($update_date));\r
+ $author_node = $xml_object->addChild("author");\r
+ $author_name = $author_node->addChild("name", htmlentities("Constant Contact"));\r
+ $content_node = $xml_object->addChild("content");\r
+ $content_node->addAttribute("type", "application/vnd.ctct+xml");\r
+ $campaign_node = $content_node->addChild("Campaign");\r
+ $campaign_node->addAttribute("xmlns", "http://ws.constantcontact.com/ns/1.0/");\r
+ $campaign_node->addAttribute("id", $id); //[2nd *id]\r
+ $name_node = $campaign_node->addChild("Name", urldecode(htmlspecialchars($params['cmp_name'], ENT_QUOTES, 'UTF-8')));\r
+ $campaign_status = !empty($params['cmp_status'])\r
+ ? ($params['cmp_status'])\r
+ : ('Draft');\r
+ $status_node = $campaign_node->addChild("Status", urldecode(htmlentities($campaign_status)));\r
+ $campaign_date = !empty($params['cmp_date'])\r
+ ? ($params['cmp_date'])\r
+ : ($update_date);\r
+ $date_node = $campaign_node->addChild("Date", urldecode(htmlentities($campaign_date)));\r
+ $subj_node = $campaign_node->addChild("Subject", urldecode(htmlspecialchars($params['cmp_subject'], ENT_QUOTES, 'UTF-8')));\r
+ $from_name_node = $campaign_node->addChild("FromName", urldecode(htmlspecialchars($params['cmp_from_name'], ENT_QUOTES, 'UTF-8')));\r
+ $view_as_webpage = (!empty($params['cmp_as_webpage']) && $params['cmp_as_webpage'] == 'YES')\r
+ ? ('YES')\r
+ : ('NO');\r
+ $as_webpage_node = $campaign_node->addChild("ViewAsWebpage", urldecode(htmlentities($view_as_webpage)));\r
+ #$as_web_lnk_txt = ($view_as_webpage == 'YES') ? ($params['cmp_as_weblink']) : ('');\r
+ $as_web_lnk_txt = $params['cmp_as_weblink'];\r
+ $as_weblink_node = $campaign_node->addChild("ViewAsWebpageLinkText", urldecode(htmlspecialchars(($as_web_lnk_txt), ENT_QUOTES, 'UTF-8')));\r
+ #$as_web_txt = ($view_as_webpage == 'YES') ? ($params['cmp_as_webtxt']) : ('');\r
+ $as_web_txt = $params['cmp_as_webtxt'];\r
+ $as_webtxt_node = $campaign_node->addChild("ViewAsWebpageText", urldecode(htmlspecialchars(($as_web_txt), ENT_QUOTES, 'UTF-8')));\r
+ $perm_reminder_node = $campaign_node->addChild("PermissionReminder", urldecode(htmlentities($params['cmp_perm_reminder'])));\r
+ $permission_reminder_text = ($params['cmp_perm_reminder'] == 'YES')\r
+ ? ($params['cmp_txt_reminder'])\r
+ : ('');\r
+ $text_reminder_node = $campaign_node->addChild("PermissionReminderText", urldecode(htmlspecialchars(($permission_reminder_text), ENT_QUOTES, 'UTF-8')));\r
+ $grt_sal_node = $campaign_node->addChild("GreetingSalutation", htmlspecialchars(($params['cmp_grt_sal']), ENT_QUOTES, 'UTF-8'));\r
+ $grt_name_node = $campaign_node->addChild("GreetingName", htmlentities($params['cmp_grt_name']));\r
+ $grt_str_node = $campaign_node->addChild("GreetingString", htmlspecialchars($params['cmp_grt_str'], ENT_QUOTES, 'UTF-8'));\r
+ $org_name_node = $campaign_node->addChild("OrganizationName", htmlspecialchars($params['cmp_org_name'], ENT_QUOTES, 'UTF-8'));\r
+ $org_addr1_node = $campaign_node->addChild("OrganizationAddress1", htmlspecialchars($params['cmp_org_addr1'], ENT_QUOTES, 'UTF-8'));\r
+ $org_addr2_node = $campaign_node->addChild("OrganizationAddress2", htmlspecialchars($params['cmp_org_addr2'], ENT_QUOTES, 'UTF-8'));\r
+ $org_addr3_node = $campaign_node->addChild("OrganizationAddress3", htmlspecialchars($params['cmp_org_addr3'], ENT_QUOTES, 'UTF-8'));\r
+ $org_city_node = $campaign_node->addChild("OrganizationCity", htmlspecialchars($params['cmp_org_city'], ENT_QUOTES, 'UTF-8'));\r
+ switch ($params['org_country']) {\r
+ case 'us':\r
+ $us_state = $params['org_state_us'];\r
+ break;\r
+ case 'ca':\r
+ $us_state = $params['org_state_us'];\r
+ break;\r
+ default:\r
+ $us_state = '';\r
+ }\r
+ $org_state_us_node = $campaign_node->addChild("OrganizationState", htmlentities($us_state));\r
+ switch ($params['org_country']) {\r
+ case 'us':\r
+ $international_state = '';\r
+ break;\r
+ case 'ca':\r
+ $international_state = '';\r
+ break;\r
+ default:\r
+ $international_state = htmlspecialchars($params['org_state'], ENT_QUOTES, 'UTF-8');\r
+ }\r
+ $org_state_name = $campaign_node->addChild("OrganizationInternationalState", htmlentities($international_state));\r
+ $org_country_node = $campaign_node->addChild("OrganizationCountry", htmlentities($params['org_country']));\r
+ $org_zip_node = $campaign_node->addChild("OrganizationPostalCode", htmlspecialchars($params['org_zip'], ENT_QUOTES, 'UTF-8'));\r
+ $include_fwd_email = (!empty($params['cmp_forward']) && $params['cmp_forward'] == 'YES')\r
+ ? ('YES')\r
+ : ('NO');\r
+ #$fwd_txt = ($include_fwd_email == 'YES') ? ($params['cmp_fwd_email']) :('');\r
+ $fwd_txt = $params['cmp_fwd_email'];\r
+ $fwd_node = $campaign_node->addChild("IncludeForwardEmail", htmlentities($include_fwd_email));\r
+ $fwd_email_node = $campaign_node->addChild("ForwardEmailLinkText", htmlspecialchars(($fwd_txt), ENT_QUOTES, 'UTF-8'));\r
+ $include_sub_link = (!empty($params['cmp_subscribe']) && $params['cmp_subscribe'] == 'YES')\r
+ ? ('YES')\r
+ : ('NO');\r
+ $sub_node = $campaign_node->addChild("IncludeSubscribeLink", htmlentities($include_sub_link));\r
+ #$sub_txt = ($include_sub_link == 'YES') ? ($params['cmp_sub_link']) : ('');\r
+ $sub_txt = $params['cmp_sub_link'];\r
+ $sub_link_node = $campaign_node->addChild("SubscribeLinkText", htmlspecialchars(($sub_txt), ENT_QUOTES, 'UTF-8'));\r
+ $email_format_node = $campaign_node->addChild("EmailContentFormat", $params['cmp_mail_type']);\r
+ if ($params['cmp_type'] != 'STOCK') {\r
+ $html_body_node = $campaign_node->addChild("EmailContent", htmlspecialchars($params['cmp_html_body'], ENT_QUOTES, 'UTF-8'));\r
+ $text_body_node = $campaign_node->addChild("EmailTextContent", "<Text>" . htmlspecialchars(strip_tags($params['cmp_text_body']), ENT_QUOTES, 'UTF-8') . "</Text>");\r
+ $campaign_style_sheet = ($params['cmp_mail_type'] == 'XHTML')\r
+ ? ($params['cmp_style_sheet'])\r
+ : ('');\r
+ $style_sheet_node = $campaign_node->addChild("StyleSheet", htmlspecialchars($campaign_style_sheet, ENT_QUOTES, 'UTF-8'));\r
+ }\r
+ $campaignlists_node = $campaign_node->addChild("ContactLists");\r
+\r
+ if ($params['lists']) {\r
+ foreach ($params['lists'] as $list) {\r
+ $campaignlist_node = $campaignlists_node->addChild("ContactList");\r
+ $campaignlist_node->addAttribute("id", $list);\r
+ $campaignlink_node = $campaignlist_node->addChild("link");\r
+ $campaignlink_node->addAttribute("xmlns", "http://www.w3.org/2005/Atom");\r
+ $campaignlink_node->addAttribute("href", str_replace("http://api.constantcontact.com", "", $list));\r
+ $campaignlink_node->addAttribute("rel", "self");\r
+ }\r
+ }\r
+\r
+ $cmp_from_email = explode('|', $params['cmp_from_email']);\r
+ $fromemail_node = $campaign_node->addChild("FromEmail");\r
+ $femail_node = $fromemail_node->addChild("Email");\r
+ $femail_node->addAttribute("id", $cmp_from_email[1]);\r
+ $femail_node_link = $femail_node->addChild("link");\r
+ $femail_node_link->addAttribute("xmlns", "http://www.w3.org/2005/Atom");\r
+ $femail_node_link->addAttribute("href", str_replace("http://api.constantcontact.com", "", $cmp_from_email[1]));\r
+ $femail_node_link->addAttribute("rel", "self");\r
+ $femail_addrs_node = $fromemail_node->addChild("EmailAddress", htmlentities($cmp_from_email[0]));\r
+ $cmp_reply_email = explode('|', $params['cmp_reply_email']);\r
+ $replyemail_node = $campaign_node->addChild("ReplyToEmail");\r
+ $remail_node = $replyemail_node->addChild("Email");\r
+ $remail_node->addAttribute("id", $cmp_reply_email[1]);\r
+ $remail_node_link = $remail_node->addChild("link");\r
+ $remail_node_link->addAttribute("xmlns", "http://www.w3.org/2005/Atom");\r
+ $remail_node_link->addAttribute("href", str_replace("http://api.constantcontact.com", "", $cmp_reply_email[1]));\r
+ $remail_node_link->addAttribute("rel", "self");\r
+ $remail_addrs_node = $replyemail_node->addChild("EmailAddress", htmlentities($cmp_reply_email[0]));\r
+ $source_node = $xml_object->addChild("source");\r
+ $sourceid_node = $source_node->addChild("id", $standard_id); //[3th *id]\r
+ $sourcetitle_node = $source_node->addChild("title", "Campaigns for customer: " . $this->login);\r
+ $sourcetitle_node->addAttribute("type", "text");\r
+ $sourcelink1_node = $source_node->addChild("link");\r
+ $sourcelink1_node->addAttribute("href", "campaigns"); //[2nd *href]\r
+ $sourcelink2_node = $source_node->addChild("link");\r
+ $sourcelink2_node->addAttribute("href", "campaigns"); //[3th *href]\r
+ $sourcelink2_node->addAttribute("rel", "self");\r
+ $sourceauthor_node = $source_node->addChild("author");\r
+ $sauthor_name = $sourceauthor_node->addChild("name", $this->login);\r
+ $sourceupdate_node = $source_node->addChild("updated", htmlentities($update_date));\r
+\r
+ $entry = $xml_object->asXML();\r
+ // $search = array('>', '\"', ' ', ' ', '"/>', '&', '&lt;', '�', '�');\r
+ // $replace = array('>', '"', '', '', '" />', '&', '<', '&Yuml;', '&yuml;');\r
+ // $entry = str_replace($search, $replace, $entry);\r
+\r
+ if ($this->sent_recived_debug) {\r
+ echo "<div><p style=\"color: blue\">We sent the following XML:</p> $entry </div><hr/>";\r
+ }\r
+\r
+ return $entry;\r
+ }\r
+\r
+}\r
--- /dev/null
+<?php
+/**
+ * StreamSend.php
+ *
+ * PHP version 5
+ *
+ * All Right Reserved
+ *
+ * @category Contacts
+ * @package LeadManager
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2009 Gaslight Media
+ * @license Gaslight Media
+ * @version CVS: $Id: StreamSend.php,v 1.5 2010/04/30 19:02:10 matrix 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 LeadManager
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2009 Gaslight Media
+ * @license Gaslight Media
+ * @link <>
+ */
+class Toolkit_LeadManager_Affiliates_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',
+ 'interest' => 'interests',
+ 'contact_type' => 'contact-type'
+ );
+
+ /**
+ * 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;
+ $ret = $ss->contactSearch($values['email']);
+
+ $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';
+ }
+ }
+ if ($ret->contact) {
+ $contacts = $ss->contactUpdate(
+ $ret->contact->id,
+ $contactData
+ );
+ } else {
+ $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 "<p>A total and complete failure occured.";
+ break;
+ case "PRODUCTION":
+ break;
+ }
+ }
+ if ($ss->debug == true) {
+ echo '<p><h3>Debug Results</h3>'.$ss->debugBuffer.'</p>';
+ }
+ return true;
+ }
+ return false;
+ }
+
+
+ // }}}
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * ConstantContact.php
+ *
+ * PHP version 5.2
+ *
+ * @category Toolkit
+ * @package LeadManager
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: $Id$
+ * @link <>
+ */
+
+require_once BASE . 'Toolkit/LeadManager/Affiliates/ConstantContact.php';
+/**
+ * Require the Constant Contact Classes
+ */
+/**
+ * Toolkit_Package_ConstantContact
+ *
+ * Description of ConstantContact
+ *
+ * @category Toolkit
+ * @package LeadManager
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @release SVN: $Id$
+ * @link <>
+ */
+class Toolkit_LeadManager_ConstantContact
+ extends Toolkit_LeadManager_Observer
+{
+ /**
+ * Send LeadManager_Lead object (contact or customer) to ConstantContact
+ *
+ * @param type $subject Object Reference for LeadManager_Lead type
+ *
+ * @return void
+ */
+ public function send(Toolkit_LeadManager_Lead $subject)
+ {
+ // have to convert the $subject Object to an array to be used
+ // in the streamsend call to addContact
+ $values = array(
+ 'email_address' => $subject->getEmail(),
+ 'first_name' => $subject->getFname(),
+ 'last_name' => $subject->getLname(),
+ 'city_name' => $subject->getCity(),
+ 'state_code' => $subject->getState(),
+ 'state_name' => $GLOBALS['states'][$subject->getState()],
+ 'zip_code' => $subject->getZip(),
+ 'home_number' => $subject->getPhone()
+ );
+ if ($subject instanceof Toolkit_LeadManager_Contact) {
+ $values['address_line_1'] = $subject->getAddress();
+ $values['address_line_2'] = $subject->getAddress2();
+ } else if ($subject instanceof Toolkit_LeadManager_Customer) {
+ $values['address_line_1'] = $subject->getAdd1();
+ $values['address_line_2'] = $subject->getAdd2();
+ }
+ if (defined('CONSTANT_CONTACT_LIST') && CONSTANT_CONTACT_LIST) {
+ $lists = unserialize(CONSTANT_CONTACT_LIST);
+ }
+ $values["lists"] = $lists;
+ $ccContactOBJ = new CC_Contact();
+ $constantContact = $ccContactOBJ->getSubscribers(
+ urlencode($values['email_address'])
+ );
+ try {
+ if (!empty($constantContact['items'])) {
+ // update contact
+ $contactXML = $ccContactOBJ->createContactXML(
+ $constantContact['id'],
+ $values
+ );
+ } else {
+ // add new contact to constant contact
+ $contactXML = $ccContactOBJ->createContactXML(
+ null,
+ $values
+ );
+ $ccContactOBJ->addSubscriber($contactXML);
+ }
+ } catch(Exception $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Contact.php
+ *
+ * PHP version 5.2
+ *
+ * @category Toolkit
+ * @package LeadManager
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: $Id$
+ * @link <>
+ */
+
+/**
+ * Toolkit_Package_Contact
+ *
+ * Class Contact used for contact integration with Stream Send
+ * Contant Contact and Mail Chimp programs.
+ *
+ * @category Toolkit
+ * @package LeadManager
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @release SVN: $Id$
+ * @link <>
+ */
+class Toolkit_LeadManager_Contact
+ extends Toolkit_LeadManager_Lead
+{
+ public static $tableName = 'contact';
+ public static $primaryKey = 'id';
+ private $_id;
+ private $_address;
+ private $_address2;
+ private $_member_ok;
+ private $_members;
+ private $_gift_cer;
+ private $_comments;
+ private $_discover;
+ private $_password;
+ private $_verify_password;
+
+ /**
+ * Contructor for class Contact Objects
+ *
+ * @param type $values Array of Values to create object with
+ */
+ public function __construct(Array $values)
+ {
+ parent::__construct($values);
+ extract($values);
+ $this->setAddress($address)
+ ->setAddress2($address2)
+ ->setComments($comments)
+ ->setDiscover($discover)
+ ->setGiftCert($gift_cert)
+ ->setMembers($members)
+ ->setMemberOk($member_ok)
+ ->setPassword($password)
+ ->setVerifyPassword($verify_password);
+ if ($id) {
+ $this->setId($id);
+ }
+ }
+
+ /**
+ * Creates a Contact class object with values given
+ *
+ * @param type $values Array of values for the contact
+ *
+ * @return Toolkit_Contacts_Admin_Contact
+ */
+ public static function createByValues($values)
+ {
+ return new Toolkit_LeadManager_Contact($values);
+ }
+
+ /**
+ * Returns the Contact Id
+ *
+ * @return type
+ */
+ public function getId()
+ {
+ return $this->_id;
+ }
+
+ /**
+ * sets the id of object
+ *
+ * @param Int $id set the id of object if not numeric throw Exception
+ *
+ * @return Toolkit_Table
+ */
+ public function setId($id)
+ {
+ if (!is_numeric($id)) {
+ throw new Exception('id must be an integer');
+ }
+ if (!$this->_id) {
+ $this->_id = $id;
+ }
+ return $this;
+ }
+
+ /**
+ * Returns the Contact Address
+ *
+ * @return type
+ */
+ public function getAddress()
+ {
+ return $this->_address;
+ }
+
+ /**
+ * Sets the Contact Address
+ *
+ * @param type $address Cotnact Address
+ *
+ * @return Toolkit_Contacts_Admin_Contact
+ */
+ public function setAddress($address)
+ {
+ $this->_address = $address;
+ return $this;
+ }
+
+ /**
+ * Returns the Contact Address2
+ *
+ * @return type
+ */
+ public function getAddress2()
+ {
+ return $this->_address2;
+ }
+
+ /**
+ * Sets the Contact Address2
+ *
+ * @param type $address2 Contact Address2
+ *
+ * @return Toolkit_Contacts_Admin_Contact
+ */
+ public function setAddress2($address2)
+ {
+ $this->_address2 = $address2;
+ return $this;
+ }
+
+ /**
+ * Returns the Contact Member OK
+ *
+ * @return type
+ */
+ public function getMemberOk()
+ {
+ return $this->_member_ok;
+ }
+
+ /**
+ * Sets the Contact Member OK
+ *
+ * @param type $member_ok Contacts Member Ok
+ *
+ * @return Toolkit_Contacts_Admin_Contact
+ */
+ public function setMemberOk($member_ok)
+ {
+ $this->_member_ok = $member_ok;
+ return $this;
+ }
+
+ /**
+ * Returns the Contact Member
+ *
+ * @return type
+ */
+ public function getMembers()
+ {
+ return $this->_members;
+ }
+
+ /**
+ * Sets the Contact Member
+ *
+ * @param type $members Contact Member
+ *
+ * @return Toolkit_Contacts_Admin_Contact
+ */
+ public function setMembers($members)
+ {
+ $this->_members = $members;
+ return $this;
+ }
+
+ /**
+ * Returns the Contact Gift Cert
+ *
+ * @return type
+ */
+ public function getGiftCert()
+ {
+ return $this->_gift_cer;
+ }
+
+ /**
+ * Sets the Contacts gift Cert
+ *
+ * @param type $gift_cert Contact gift_cert
+ *
+ * @return Toolkit_Contacts_Admin_Contact
+ */
+ public function setGiftCert($gift_cert)
+ {
+ $this->_gift_cer = $gift_cert;
+ return $this;
+ }
+
+ /**
+ * Returns the Contacts Comments
+ *
+ * @return type
+ */
+ public function getComments()
+ {
+ return $this->_comments;
+ }
+
+ /**
+ * Sets the Contacts Comments
+ *
+ * @param type $comments Contact Comments
+ *
+ * @return Toolkit_Contacts_Admin_Contact
+ */
+ public function setComments($comments)
+ {
+ $this->_comments = $comments;
+ return $this;
+ }
+
+ /**
+ * Returns Contacts Discover Field
+ *
+ * @return type
+ */
+ public function getDiscover()
+ {
+ return $this->_discover;
+ }
+
+ /**
+ * Sets the Contacts Discover field
+ *
+ * @param type $discover Contacts Discover field
+ *
+ * @return Toolkit_Contacts_Admin_Contact
+ */
+ public function setDiscover($discover)
+ {
+ $this->_discover = $discover;
+ return $this;
+ }
+
+ /**
+ * Returns the leads password
+ *
+ * @return type
+ */
+ public function getPassword()
+ {
+ return $this->_password;
+ }
+
+ /**
+ * Sets the leads password
+ *
+ * @param type $password led password
+ *
+ * @return Toolkit_Contacts_Admin_Lead
+ */
+ public function setPassword($password)
+ {
+ $this->_password = $password;
+ return $this;
+ }
+
+ /**
+ * Returns the Verify Password
+ *
+ * @return string
+ */
+ public function getVerifyPassword()
+ {
+ return $this->_verify_password;
+ }
+
+ /**
+ * Sets the verify_password
+ *
+ * @param string $verifyPassword
+ */
+ public function setVerifyPassword($verifyPassword)
+ {
+ $this->_verify_password = $verifyPassword;
+ }
+
+
+}
--- /dev/null
+<?php
+
+/**
+ * Customer.php
+ *
+ * PHP version 5.2
+ *
+ * @category Toolkit
+ * @package LeadManager
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: $Id$
+ * @link <>
+ */
+
+/**
+ * Toolkit_Package_Customer
+ *
+ * Description of Customer
+ *
+ * @category Toolkit
+ * @package LeadManager
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @release SVN: $Id$
+ * @link <>
+ */
+class Toolkit_LeadManager_Customer
+ extends Toolkit_LeadManager_Lead
+{
+ public static $tableName = 'customer';
+ public static $primaryKey = 'cust_id';
+ private $_cust_id;
+ private $_userid;
+ private $_usernum;
+ private $_usergroup;
+ private $_add1;
+ private $_add2;
+ private $_org;
+ private $_access_date;
+ private $_purch_date;
+ private $_referred_by;
+ private $_promo;
+ private $_ship_type;
+ private $_club;
+ private $_wherefrom;
+ private $_addr_ext;
+ private $_salutation;
+
+ /**
+ * Constructor for class Customer objects
+ *
+ * @param array $values Array of values
+ */
+ public function __construct(array $values)
+ {
+ parent::__construct($values);
+ extract($values);
+ $this->setUserid($user_id)
+ ->setUsernum($usernum)
+ ->setUsergroup($usergroup)
+ ->setAdd1($add1)
+ ->setAdd2($add2)
+ ->setOrg($org)
+ ->setAccessDate($access_date)
+ ->setPurchDate($purch_date)
+ ->setReferredBy($referred_by)
+ ->setPromo($promo)
+ ->setShipType($ship_type)
+ ->setClub($club)
+ ->setWherefrom($wherefrom)
+ ->setAddrExt($addr_ext)
+ ->setSalutation($salutation);
+ if ($cust_id) {
+ $this->setCustId($cust_id);
+ }
+ }
+
+ /**
+ * Creates a Contact class object with values given
+ *
+ * @param type $values Array of values for the contact
+ *
+ * @return Toolkit_Contacts_Admin_Contact
+ */
+ public static function createByValues($values)
+ {
+ return new Toolkit_LeadManager_Customer($values);
+ }
+
+ /**
+ * Returns cust_id
+ *
+ * @return type
+ */
+ public function getCustId()
+ {
+ return $this->_cust_id;
+ }
+
+ /**
+ * Sets the customer cust_id
+ *
+ * @param type $_cust_id Customer cust_id
+ *
+ * @return Toolkit_LeadManager_Customer
+ */
+ public function setCustId($_cust_id)
+ {
+ $this->_cust_id = $_cust_id;
+ return $this;
+ }
+
+ /**
+ * Returns Customer userid
+ *
+ * @return type
+ */
+ public function getUserid()
+ {
+ return $this->_userid;
+ }
+
+ /**
+ * Sets Customer userid
+ *
+ * @param type $_userid Customer Userid
+ *
+ * @return Toolkit_LeadManager_Customer
+ */
+ public function setUserid($_userid)
+ {
+ $this->_userid = $_userid;
+ return $this;
+ }
+
+ /**
+ * Returns Customer usernum
+ *
+ * @return type
+ */
+ public function getUsernum()
+ {
+ return $this->_usernum;
+ }
+
+ /**
+ * Sets Customer usernum
+ *
+ * @param type $_usernum Customer usernum
+ *
+ * @return Toolkit_LeadManager_Customer
+ */
+ public function setUsernum($_usernum)
+ {
+ $this->_usernum = $_usernum;
+ return $this;
+ }
+
+ /**
+ * Returns Customer Usergroup
+ *
+ * @return type
+ */
+ public function getUsergroup()
+ {
+ return $this->_usergroup;
+ }
+
+ /**
+ * Sets Customer usergroup
+ *
+ * @param type $_usergroup Customer usergroup
+ *
+ * @return Toolkit_LeadManager_Customer
+ */
+ public function setUsergroup($_usergroup)
+ {
+ $this->_usergroup = $_usergroup;
+ return $this;
+ }
+
+ /**
+ * Returns Customer add1
+ *
+ * @return type
+ */
+ public function getAdd1()
+ {
+ return $this->_add1;
+ }
+
+ /**
+ * Sets Customer add1
+ *
+ * @param type $_add1 Customer add1
+ *
+ * @return Toolkit_LeadManager_Customer
+ */
+ public function setAdd1($_add1)
+ {
+ $this->_add1 = $_add1;
+ return $this;
+ }
+
+ /**
+ * Returns Customer add2
+ *
+ * @return type
+ */
+ public function getAdd2()
+ {
+ return $this->_add2;
+ }
+
+ /**
+ * Sets Customer addr2
+ *
+ * @param type $_add2 Customer add2
+ *
+ * @return Toolkit_LeadManager_Customer
+ */
+ public function setAdd2($_add2)
+ {
+ $this->_add2 = $_add2;
+ return $this;
+ }
+
+ /**
+ * Returns Customer org
+ *
+ * @return type
+ */
+ public function getOrg()
+ {
+ return $this->_org;
+ }
+
+ /**
+ * Sets Customer org
+ *
+ * @param type $_org Customer org
+ *
+ * @return Toolkit_LeadManager_Customer
+ */
+ public function setOrg($_org)
+ {
+ $this->_org = $_org;
+ return $this;
+ }
+
+ /**
+ * Returns Customer access_date
+ *
+ * @return type
+ */
+ public function getAccessDate()
+ {
+ return $this->_access_date;
+ }
+
+ /**
+ * Sets Customer acces_date
+ *
+ * @param type $_access_date Customer access_date
+ *
+ * @return Toolkit_LeadManager_Customer
+ */
+ public function setAccessDate($_access_date)
+ {
+ $this->_access_date = $_access_date;
+ return $this;
+ }
+
+ /**
+ * Returns Customer purch_date
+ *
+ * @return type
+ */
+ public function getPurchDate()
+ {
+ return $this->_purch_date;
+ }
+
+ /**
+ * Sets Customer purch_date
+ *
+ * @param type $_purch_date Customer purch_date
+ *
+ * @return Toolkit_LeadManager_Customer
+ */
+ public function setPurchDate($_purch_date)
+ {
+ $this->_purch_date = $_purch_date;
+ return $this;
+ }
+
+ /**
+ * Returns Customer Referred_by
+ *
+ * @return type
+ */
+ public function getReferredBy()
+ {
+ return $this->_referred_by;
+ }
+
+ /**
+ * Sets Customer referred_by
+ *
+ * @param type $_referred_by Customer referred_by
+ *
+ * @return Toolkit_LeadManager_Customer
+ */
+ public function setReferredBy($_referred_by)
+ {
+ $this->_referred_by = $_referred_by;
+ return $this;
+ }
+
+ /**
+ * Returns Customer promo
+ *
+ * @return type
+ */
+ public function getPromo()
+ {
+ return $this->_promo;
+ }
+
+ /**
+ * Sets Customer promo
+ *
+ * @param type $_promo Customer promo
+ *
+ * @return Toolkit_LeadManager_Customer
+ */
+ public function setPromo($_promo)
+ {
+ $this->_promo = $_promo;
+ return $this;
+ }
+
+ /**
+ * Returns Customer ship_type
+ *
+ * @return type
+ */
+ public function getShipType()
+ {
+ return $this->_ship_type;
+ }
+
+ /**
+ * Sets Customer ship_type
+ *
+ * @param type $_ship_type Customer ship_type
+ *
+ * @return Toolkit_LeadManager_Customer
+ */
+ public function setShipType($_ship_type)
+ {
+ $this->_ship_type = $_ship_type;
+ return $this;
+ }
+
+ /**
+ * Returns Customer club
+ *
+ * @return type
+ */
+ public function getClub()
+ {
+ return $this->_club;
+ }
+
+ /**
+ * Sets Customer club
+ *
+ * @param type $_club Customer club
+ *
+ * @return Toolkit_LeadManager_Customer
+ */
+ public function setClub($_club)
+ {
+ $this->_club = $_club;
+ return $this;
+ }
+
+ /**
+ * Returns Customer wherefrom
+ *
+ * @return type
+ */
+ public function getWherefrom()
+ {
+ return $this->_wherefrom;
+ }
+
+ /**
+ * Sets Customer wherefrom
+ *
+ * @param type $_wherefrom Customer wherefrom
+ *
+ * @return Toolkit_LeadManager_Customer
+ */
+ public function setWherefrom($_wherefrom)
+ {
+ $this->_wherefrom = $_wherefrom;
+ return $this;
+ }
+
+ /**
+ * Returns Customer Addr_ext
+ *
+ * @return type
+ */
+ public function getAddrExt()
+ {
+ return $this->_addr_ext;
+ }
+
+ /**
+ * Sets Customer addr_ext
+ *
+ * @param type $_addr_ext Customer addr_ext
+ *
+ * @return Toolkit_LeadManager_Customer
+ */
+ public function setAddrExt($_addr_ext)
+ {
+ $this->_addr_ext = $_addr_ext;
+ return $this;
+ }
+
+ /**
+ * Returns Customer Salutation
+ *
+ * @return type
+ */
+ public function getSalutation()
+ {
+ return $this->_salutation;
+ }
+
+ /**
+ * Sets Customer salutation
+ *
+ * @param type $_salutation Customer Salutation
+ *
+ * @return Toolkit_LeadManager_Customer
+ */
+ public function setSalutation($_salutation)
+ {
+ $this->_salutation = $_salutation;
+ return $this;
+ }
+
+}
--- /dev/null
+<?php
+
+/**
+ * Lead.php
+ *
+ * PHP version 5.2
+ *
+ * @category Toolkit
+ * @package LeadManager
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: $Id$
+ * @link <>
+ */
+
+/**
+ * Toolkit_Package_Lead
+ *
+ * Abstract class Lead used for contact integration with Stream Send
+ * Contant Contact and Mail Chimp programs.
+ *
+ * @category Toolkit
+ * @package LeadManager
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @release SVN: $Id$
+ * @link <>
+ */
+abstract class Toolkit_LeadManager_Lead
+ extends Toolkit_LeadManager_Subject
+{
+ private $_create_date;
+ private $_email;
+ private $_fname;
+ private $_lname;
+ private $_city;
+ private $_state;
+ private $_zip;
+ private $_country;
+ private $_phone;
+ private $_fax;
+ private $_user_agent;
+ private $_remote_addr;
+ private $_mail_ok;
+ private $_interest;
+ private $_contact_type;
+
+ /**
+ * Constructor for Lead class objects
+ *
+ * @param type $values Array of Values for Lead
+ */
+ public function __construct(Array $values)
+ {
+ extract($values);
+ $this->setCreateDate($create_date)
+ ->setEmail($email)
+ ->setFname($fname)
+ ->setLname($lname)
+ ->setCity($city)
+ ->setState($state)
+ ->setZip($zip)
+ ->setCountry($country)
+ ->setPhone($phone)
+ ->setFax($fax)
+ ->setUserAgent($user_agent)
+ ->setRemoteAddr($remote_addr)
+ ->setMailOk($mail_ok)
+ ->setInterest($interest)
+ ->setContactType($contact_type);
+ }
+
+ /**
+ * Creates a Lead class object by passing in $values array
+ * into the Leads constructor method. Is static method
+ *
+ * @param type $values Array of values to create Lead with
+ *
+ * @return Toolkit_Contacts_Admin_Lead
+ */
+ abstract static public function createByValues($values);
+
+ /**
+ * Returns the Leads Create Date
+ *
+ * @return type
+ */
+ public function getCreateDate()
+ {
+ return $this->_create_date;
+ }
+
+ /**
+ * Sets the Leads Create Date
+ *
+ * @param type $create_date Leads Create Date
+ *
+ * @return Toolkit_Contacts_Admin_Lead
+ */
+ public function setCreateDate($create_date)
+ {
+ $this->_create_date = $create_date;
+ return $this;
+ }
+
+ /**
+ * Returs the Leads Email Address
+ *
+ * @return type
+ */
+ public function getEmail()
+ {
+ return $this->_email;
+ }
+
+ /**
+ * Sets the Leads Email Address
+ *
+ * @param type $email Leads email address
+ *
+ * @return Toolkit_Contacts_Admin_Lead
+ */
+ public function setEmail($email)
+ {
+ $this->_email = $email;
+ return $this;
+ }
+
+ /**
+ * Returns the Leads First Name
+ *
+ * @return type
+ */
+ public function getFname()
+ {
+ return $this->_fname;
+ }
+
+ /**
+ * Sets the Leads First Name
+ *
+ * @param type $fname Leads First Name
+ *
+ * @return Toolkit_Contacts_Admin_Lead
+ */
+ public function setFname($fname)
+ {
+ $this->_fname = $fname;
+ return $this;
+ }
+
+ /**
+ * Returns the Leads Last Name
+ *
+ * @return type
+ */
+ public function getLname()
+ {
+ return $this->_lname;
+ }
+
+ /**
+ * Sets the Leads Last Name
+ *
+ * @param type $lname Leads Last Name
+ *
+ * @return Toolkit_Contacts_Admin_Lead
+ */
+ public function setLname($lname)
+ {
+ $this->_lname = $lname;
+ return $this;
+ }
+
+ /**
+ * Returns the Leads city
+ *
+ * @return type
+ */
+ public function getCity()
+ {
+ return $this->_city;
+ }
+
+ /**
+ * Sets the Leads city
+ *
+ * @param type $city Leads city
+ *
+ * @return Toolkit_Contacts_Admin_Lead
+ */
+ public function setCity($city)
+ {
+ $this->_city = $city;
+ return $this;
+ }
+
+ /**
+ * Returns the Leads state
+ *
+ * @return type
+ */
+ public function getState()
+ {
+ return $this->_state;
+ }
+
+ /**
+ * Sets the Leads state
+ *
+ * @param type $state Leads state
+ *
+ * @return Toolkit_Contacts_Admin_Lead
+ */
+ public function setState($state)
+ {
+ $this->_state = $state;
+ return $this;
+ }
+
+ /**
+ * Returns the Leads zip code
+ *
+ * @return type
+ */
+ public function getZip()
+ {
+ return $this->_zip;
+ }
+
+ /**
+ * Sets the Leads zip code
+ *
+ * @param type $zip Leads Zip code
+ *
+ * @return Toolkit_Contacts_Admin_Lead
+ */
+ public function setZip($zip)
+ {
+ $this->_zip = $zip;
+ return $this;
+ }
+
+ /**
+ * Returns the Leads country
+ *
+ * @return type
+ */
+ public function getCountry()
+ {
+ return $this->_country;
+ }
+
+ /**
+ * Sets the Leads country
+ *
+ * @param type $country Leads country
+ *
+ * @return Toolkit_Contacts_Admin_Lead
+ */
+ public function setCountry($country)
+ {
+ $this->_country = $country;
+ return $this;
+ }
+
+ /**
+ * Returns the Leads phone number
+ *
+ * @return type
+ */
+ public function getPhone()
+ {
+ return $this->_phone;
+ }
+
+ /**
+ * Sets the Leads phone number
+ *
+ * @param type $phone Leads phone number
+ *
+ * @return Toolkit_Contacts_Admin_Lead
+ */
+ public function setPhone($phone)
+ {
+ $this->_phone = $phone;
+ return $this;
+ }
+
+ /**
+ * Returns the Leads fax number
+ *
+ * @return type
+ */
+ public function getFax()
+ {
+ return $this->_fax;
+ }
+
+ /**
+ * Sets the Leads fax number
+ *
+ * @param type $fax Leads fax number
+ *
+ * @return Toolkit_Contacts_Admin_Lead
+ */
+ public function setFax($fax)
+ {
+ $this->_fax = $fax;
+ return $this;
+ }
+
+ /**
+ * Returns the Leads user agent
+ *
+ * @return type
+ */
+ public function getUserAgent()
+ {
+ return $this->_user_agent;
+ }
+
+ /**
+ * Sets the Leads user agent
+ *
+ * @param type $user_agent Leads user agent
+ *
+ * @return Toolkit_Contacts_Admin_Lead
+ */
+ public function setUserAgent($user_agent)
+ {
+ $this->_user_agent = $user_agent;
+ return $this;
+ }
+
+ /**
+ * Returns the Leads remote address
+ *
+ * @return type
+ */
+ public function getRemoteAddr()
+ {
+ return $this->_remote_addr;
+ }
+
+ /**
+ * Sets the Leads remote address
+ *
+ * @param type $remote_addr Leads remote address
+ *
+ * @return Toolkit_Contacts_Admin_Lead
+ */
+ public function setRemoteAddr($remote_addr)
+ {
+ $this->_remote_addr = $remote_addr;
+ return $this;
+ }
+
+ /**
+ * Returns the Leads mail_ok
+ *
+ * @return type
+ */
+ public function getMailOk()
+ {
+ return $this->_mail_ok;
+ }
+
+ /**
+ * Sets the Leads mail_ok
+ *
+ * @param type $mail_ok Leads mail ok
+ *
+ * @return Toolkit_Contacts_Admin_Lead
+ */
+ public function setMailOk($mail_ok)
+ {
+ $this->_mail_ok = $mail_ok;
+ return $this;
+ }
+
+ /**
+ * Returns the Leads interests
+ *
+ * @return type
+ */
+ public function getInterest()
+ {
+ return $this->_interest;
+ }
+
+ /**
+ * Sets the leads interests
+ *
+ * @param type $interest Leads interest
+ *
+ * @return Toolkit_Contacts_Admin_Lead
+ */
+ public function setInterest($interest)
+ {
+ $this->_interest = $interest;
+ return $this;
+ }
+
+ /**
+ * Returns the leads contact type
+ *
+ * @return type
+ */
+ public function getContactType()
+ {
+ return $this->_contact_type;
+ }
+
+ /**
+ * Sets the leads contact type
+ *
+ * @param type $contact_type Leads contact type
+ *
+ * @return Toolkit_Contacts_Admin_Lead
+ */
+ public function setContactType($contact_type)
+ {
+ $this->_contact_type = $contact_type;
+ return $this;
+ }
+
+ /**
+ * Return primary key field value of table
+ *
+ * @return type
+ */
+ public function getPrimaryKey()
+ {
+ $defaultVars = get_class_vars(get_class($this));
+ $primaryKey
+ = ($defaultVars['primaryKey'] == 'cust_id')
+ ? 'CustId'
+ : ucfirst($defaultVars['primaryKey']);
+ $getPrimaryKey = "get$primaryKey";
+ return $this->$getPrimaryKey();
+ }
+
+ /**
+ * Parse out the integer references for the interest into their
+ * string names
+ *
+ * @param PDO $dbh Database connection
+ *
+ * @return type
+ */
+ public function getInterestsAsArray(PDO $dbh)
+ {
+ $interestArray = array();
+ $interest = preg_replace('/^:|:$/', '', $this->_interest);
+ $intArray
+ = (is_array($interest))
+ ? explode(':', $interest)
+ : array();
+ if (is_array($intArray)) {
+ array_filter($intArray);
+ }
+ if ($this->_interest && !empty($intArray)) {
+ try {
+ $sql = "
+ SELECT id,header
+ FROM contact_inq
+ WHERE id IN (".implode(',', $intArray).")
+ ORDER BY header";
+ $stmt = $dbh->query($sql);
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $interestArray[$row['id']] = $row['header'];
+ }
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+ return $interestArray;
+ }
+
+ /**
+ * Parse out the contact types and return array with their names
+ *
+ * @return type
+ */
+ public function getContactTypesAsArray()
+ {
+ $contactTypesArray = array();
+ $types = preg_replace('/^:|:$/', '', $this->_contact_type);
+ $typeArray = explode(':', $types);
+ if ($this->_contact_type && !empty($typeArray)) {
+ $conf = new Config();
+ $root =& $conf->parseConfig(
+ BASE . 'Toolkit/Contacts/config.ini',
+ 'IniFile'
+ );
+ // check for PEAR error
+ if (PEAR::isError($root)) {
+ Toolkit_Common::handleError($root);
+ }
+ $cTypes
+ = $root->getItem('section', 'contact_types')
+ ->toArray();
+ foreach ($typeArray as $type) {
+ $contactTypesArray[$type] = $cTypes['contact_types'][$type];
+ }
+ }
+ return $contactTypesArray;
+ }
+
+ /**
+ * Checks the id of the object if it is set then calls update othervise
+ * calls insert function
+ *
+ * @param PDO $dbh Database connection
+ * @param boolean $saveNullFields To save nul fields or not
+ *
+ * @return viod
+ */
+ public function save(PDO $dbh, $saveNullFields = true)
+ {
+ $id = $this->getPrimaryKey();
+ if ($id) {
+ $this->update($dbh, $saveNullFields);
+ } else {
+ $this->insert($dbh);
+ }
+ $this->notify();
+ }
+
+ /**
+ * insert the object
+ *
+ * @param PDO $dbh Database Connection
+ *
+ * @return Toolkit_Table
+ */
+ public function insert(PDO $dbh)
+ {
+ try {
+ $methods = get_class_methods(get_class($this));
+ $values = array();
+ if ($methods) {
+ $pattern = '/get(.*)/';
+ foreach ($methods as $mName) {
+ if ( preg_match($pattern, $mName, $matches)
+ && !in_array(
+ $mName,
+ array(
+ 'getInterestsAsArray',
+ 'getContactTypesAsArray',
+ 'getPrimaryKey'
+ )
+ )
+ ) {
+ $func = create_function(
+ '$c',
+ 'return "_" . strtolower($c[1]);'
+ );
+ $fieldName = preg_replace_callback(
+ '/([A-Z])/',
+ $func,
+ $matches[1]
+ );
+ $fieldName = preg_replace('/^_/', '', $fieldName);
+ $values[$fieldName] = $this->$matches[0]();
+ }
+ }
+ }
+ $defaultVars = get_class_vars(get_class($this));
+ $primaryKey = $defaultVars['primaryKey'];
+ $tableName = $defaultVars['tableName'];
+ unset($values[$primaryKey]);
+ $sql = Toolkit_Common::createSQLInsert(
+ $tableName,
+ array_keys($values)
+ );
+ $sql .= " RETURNING $primaryKey";
+ $stmt = Toolkit_Common::prepareQuery(
+ $dbh,
+ $tableName,
+ $sql,
+ $values
+ );
+ $stmt->execute();
+ $primaryKey
+ = ($primaryKey == 'cust_id')
+ ? 'custId'
+ : $primaryKey;
+ $setter = 'set'.ucfirst($primaryKey);
+ $this->$setter($stmt->fetchColumn());
+ return $this;
+ } catch(PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ /**
+ * update the object
+ *
+ * @param PDO $dbh Database connection
+ * @param boolean $saveNullFields To save null fields or not
+ *
+ * @return Toolkit_Table
+ */
+ public function update(PDO $dbh, $saveNullFields = true)
+ {
+ try {
+ $methods = get_class_methods(get_class($this));
+ $values = array();
+ if ($methods) {
+ $pattern = '/get(.*)/';
+ foreach ($methods as $mName) {
+ if ( preg_match($pattern, $mName, $matches)
+ && !in_array(
+ $mName,
+ array(
+ 'getInterestsAsArray',
+ 'getContactTypesAsArray',
+ 'getPrimaryKey'
+ )
+ )
+ ) {
+ $func = create_function(
+ '$c',
+ 'return "_" . strtolower($c[1]);'
+ );
+ $fieldName = preg_replace_callback(
+ '/([A-Z])/',
+ $func,
+ $matches[1]
+ );
+ $fieldName = preg_replace('/^_/', '', $fieldName);
+ $fieldValue = $this->$matches[0]();
+ if (( $fieldValue === null && $saveNullFields)
+ || $fieldValue !== null
+ ) {
+ $values[$fieldName] = $fieldValue;
+ }
+ }
+ }
+ }
+ $defaultVars = get_class_vars(get_class($this));
+ $primaryKey = $defaultVars['primaryKey'];
+ $tableName = $defaultVars['tableName'];
+ $sql = Toolkit_Common::createSQLUpdate(
+ $tableName,
+ array_keys($values),
+ array("$primaryKey = :$primaryKey")
+ );
+ $stmt = Toolkit_Common::prepareQuery(
+ $dbh,
+ $tableName,
+ $sql,
+ $values
+ );
+ $stmt->execute();
+ return $this;
+ } catch(PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Observer.php
+ *
+ * PHP version 5.2
+ *
+ * @category Toolkit
+ * @package LeadManager
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: $Id$
+ * @link <>
+ */
+
+/**
+ * Toolkit_Package_Observer
+ *
+ * Description of Observer
+ *
+ * @category Toolkit
+ * @package LeadManager
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @release SVN: $Id$
+ * @link <>
+ */
+abstract class Toolkit_LeadManager_Observer
+{
+ /**
+ * abstract method send to be used to send the contact
+ * which is a Toolkit_LeadManager_Lead to appropiate wrapper
+ *
+ * @param Toolkit_LeadManager_Lead $subject Object Lead
+ *
+ * @return void
+ */
+ abstract public function send(Toolkit_LeadManager_Lead $subject);
+
+ /**
+ * Update method for the Observer Calls the send method.
+ *
+ * @param type $subject Observer Object Reference
+ *
+ * @return void
+ */
+ public function update($subject)
+ {
+ // looks for an observer method with the send name
+ if (method_exists($this, 'send')) {
+ call_user_func_array(array($this, 'send'), array($subject));
+ }
+ }
+
+}
--- /dev/null
+<?php
+
+/**
+ * StreamSend.php
+ *
+ * PHP version 5.2
+ *
+ * @category Toolkit
+ * @package LeadManager
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: $Id$
+ * @link <>
+ */
+
+/**
+ * Toolkit_Package_StreamSend
+ *
+ * StreamSend Observer pattern for LeadManager Contact class
+ *
+ * @category Toolkit
+ * @package LeadManager
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @release SVN: $Id$
+ * @link <>
+ */
+class Toolkit_LeadManager_StreamSend
+ extends Toolkit_LeadManager_Observer
+{
+ /**
+ * Send LeadManager_Lead object (contact or customer) to StreamSend
+ *
+ * @param type $subject Object Reference for LeadManager_Lead type
+ *
+ * @return void
+ */
+ public function send(Toolkit_LeadManager_Lead $subject)
+ {
+ // have to convert the $subject Object to an array to be used
+ // in the streamsend call to addContact
+ $values = array(
+ 'email' => $subject->getEmail(),
+ 'fname' => $subject->getFname(),
+ 'lname' => $subject->getLname(),
+ 'city' => $subject->getCity(),
+ 'state' => $subject->getState(),
+ 'zip' => $subject->getZip(),
+ 'phone' => $subject->getPhone()
+ );
+ if ($subject instanceof Toolkit_LeadManager_Contact) {
+ $values['address'] = $subject->getAddress();
+ $values['address2'] = $subject->getAddress2();
+ } else if ($subject instanceof Toolkit_LeadManager_Customer) {
+ $values['address'] = $subject->getAdd1();
+ $values['address2'] = $subject->getAdd2();
+ }
+
+ $contactTypes = $subject->getContactTypesAsArray();
+ if ($contactTypes) {
+ $values['contact_type'] = implode('|', $contactTypes);
+ }
+ $interests
+ = $subject->getInterestsAsArray(Toolkit_Database::getInstance());
+ if ($interests) {
+ $values['interest'] = implode('|', $interests);
+ }
+ // call the streamsends API to send contact to stream send
+ $streamSend = new Toolkit_LeadManager_Affiliates_StreamSend();
+ $streamSend->addContact($values);
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Subject.php
+ *
+ * PHP version 5.2
+ *
+ * @category Toolkit
+ * @package LeadManager
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: $Id$
+ * @link <>
+ */
+
+/**
+ * Toolkit_Package_Subject
+ *
+ * Description of Subject
+ *
+ * @category Toolkit
+ * @package LeadManager
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @release SVN: $Id$
+ * @link <>
+ */
+abstract class Toolkit_LeadManager_Subject
+{
+ protected $observers = array();
+
+ /**
+ * Sets the Observer into the observers array
+ *
+ * @param Toolkit_LeadManager_Observer $observer Observer object to add
+ *
+ * @return void
+ */
+ public function attach(Toolkit_LeadManager_Observer $observer)
+ {
+ $i = array_search($observer, $this->observers);
+ if ($i === false) {
+ $this->observers[] = $observer;
+ }
+ }
+
+ /**
+ * Unsets the Observer from the observers array
+ *
+ * @param Toolkit_LeadManager_Observer $observer Observer to delete
+ *
+ * @return void
+ */
+ public function detach(Toolkit_LeadManager_Observer $observer)
+ {
+ if (!empty($this->observers)) {
+ $i = array_search($observer, $this->observers);
+ if ($i !== false) {
+ unset($this->observers[$i]);
+ }
+ }
+ }
+
+ /**
+ * Call each Observers update method
+ *
+ * @return void
+ */
+ public function notify()
+ {
+ if (!empty($this->observers)) {
+ foreach ($this->observers as $observer) {
+ $observer->update($this);
+ }
+ }
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * FileUploader.php
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Photos/Admin
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2009 Gaslight Media
+ * @license Gaslight Media
+ * @version CVS: $Id: ShortURL.php,v 1.5 2010/05/25 14:07:22 jamie Exp $
+ * @link <>
+ */
+
+define('YAHOO_YUI_BASE', MEDIA_APP_BASE_URL . 'yui/build/');
+define('PHOTOS_UPLOAD_PATH', BASE . 'admin/Photos/uploads/');
+
+/**
+ * Toolkit_Photos_Admin_FileUploader
+ *
+ * Description of Toolkit_Photos_Admin_FileUploader
+ *
+ * @category Toolkit
+ * @package Photos/Admin
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2014 Gaslight Media
+ * @license Gaslight Media
+ * @release Release: $id$
+ * @link <>
+ */
+class Toolkit_Photos_Admin_FileUploader
+ extends Toolkit_FormBuilder
+{
+ // {{{ Class Properties
+ /**
+ * Description of $debug
+ * @var boolean
+ */
+ public $debug = false;
+
+ /**
+ * Message for successful upload
+ * @var string
+ */
+ protected $successMsg
+ = '<div id="form-success-top">
+ You have successfully uploaded the files to your photo album.
+ </div>';
+ // }}}
+
+ // {{{ configureDefaults()
+
+ /**
+ * Initializes default form values
+ *
+ * @return void
+ * @access public
+ */
+ public function configureDefaults()
+ {
+ $defaults = array('catid' => $_REQUEST['catid']);
+
+ $this->setupDefaults($defaults);
+ }
+
+ // }}}
+ // {{{ configureElements()
+
+ /**
+ * Form element definitions
+ *
+ * @return void
+ * @access public
+ */
+ public function configureElements()
+ {
+ $e = array();
+ $categories = $this->getPhotoCategories();
+
+ // All Elements are created here. This includes group element definitions.
+ $e[] = array(
+ 'type' => 'header',
+ 'name' => 'albumHdr_rmv',
+ 'display' => '
+ <p style="width: 700px; padding-left: 5px;">
+ <strong>USE:</strong>
+ Hold down the Ctrl key to select or unselect more than one photo
+ at a time. Hold down the Shift key to select a range.</p>
+ <div style="position: absolute; top: 320px;width: 700px; border: 1px dashed #9FD8EF;padding: 20px; margin: 0 0 20px 0;">
+ This feature (Multiple Uploads) is only supported in certain modern browsers:
+ <ul>
+ <li>Internet Explorer 10</li>
+ <li>FireFox 8 and up</li>
+ <li>Safari 5 and up</li>
+ <li>Google Chrome 17 and up</li>
+ </ul>
+ </div>'
+ );
+ $e[] = array(
+ 'type' => 'hidden',
+ 'req' => false,
+ 'name' => 'catid'
+ );
+ $e[] = array(
+ 'type' => 'file',
+ 'name' => 'files[]',
+ 'display' => 'Files to Upload',
+ 'opts' => array(
+ 'id' => 'myuploader',
+ 'multiple' => 'multiple',
+ 'accept' => 'image/*'
+ )
+ );
+
+ $e[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'submit_rmv',
+ 'display' => 'Submit Form'
+ );
+
+ $this->setupElements($e);
+ }
+
+ // }}}
+ // {{{ configureFilters()
+
+ /**
+ * Form filter definitions
+ *
+ * Applies a data filter for the given fields when the form is submitted
+ *
+ * @return void
+ * @access public
+ */
+ public function configureFilters()
+ {
+ $f = array();
+
+ $f[] = array(
+ 'element' => '__ALL__',
+ 'filter' => 'trim'
+ );
+
+ $this->setupFilters($f);
+ }
+
+ // }}}
+ // {{{ configureForm()
+
+ /**
+ * Helper function, configures the entire form
+ *
+ * @return void
+ * @access public
+ */
+ public function configureForm()
+ {
+ $this->configureElements();
+ $this->configureFilters();
+ $this->configureRules();
+ $this->configureDefaults();
+ }
+
+ // }}}
+ // {{{ configureRules()
+
+ /**
+ * Form rule definitions
+ *
+ * Adds validation rules for the given fields
+ *
+ * @return void
+ * @access public
+ */
+ public function configureRules()
+ {
+ $r = array();
+ $this->setupRules($r);
+ }
+
+ // }}}
+
+ // {{{ getFileData()
+ /**
+ * Get file data
+ *
+ * @param string $fileName Filename
+ * @param string $path File path
+ *
+ * @return array|boolean
+ * @access public
+ */
+ function getFileData($fileName, $path)
+ {
+ $filename = $path . '/' . $fileName;
+ if (is_file($filename) && is_readable($filename)) {
+ return array(
+ 'name' => $fileName,
+ 'tmp_name' => $filename,
+ 'size' => filesize($filename),
+ 'type' => mime_content_type($filename)
+ );
+ } else {
+ return false;
+ }
+ }
+ // }}}
+ // {{{ getPhotoCategorieso()
+
+ /**
+ * Get photo categories
+ *
+ * @return array
+ * @access public
+ */
+ function getPhotoCategories()
+ {
+ try {
+ $sql = "
+ SELECT id, category
+ FROM photo_category
+ ORDER BY category";
+ $stmt = $this->dbh->query($sql);
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $categories[$row['id']] = $row['category'];
+ }
+ return $categories;
+ } catch(PDOExecption $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }// }}}
+ // {{{ getCategoryMaxPos()
+ /**
+ * get max pos plus one
+ *
+ * @param mixed $id photo category id
+ *
+ * @access public
+ * @return string
+ */
+ function getCategoryMaxPos($id)
+ {
+ try {
+ $sql = "
+ SELECT COALESCE(max(pos) + 1, 1)
+ FROM photo2category
+ WHERE category = :catid";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(":catid", $id, PDO::PARAM_INT);
+ $stmt->execute();
+ return $stmt->fetchColumn();
+ } catch(PDOException $e) {
+ 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 public
+ */
+ public function processData($values)
+ {
+ if ( is_array($values['files'])
+ && !empty($values['files'])) {
+ $this->processFilesArray($values);
+ } else {
+ $this->processFolder($values);
+ }
+ return true;
+ }
+
+ // }}}
+
+ /**
+ * Process files array
+ *
+ * @param array $values Values array
+ *
+ * @return void
+ * @access public
+ */
+ public function processFilesArray($values)
+ {
+ $images = array();
+ $photos = array();
+ $acceptedFiles = array(
+ 'image/jpeg',
+ 'image/gif',
+ 'image/png'
+ );
+ $is = new Toolkit_FileServer_ImageAdapter(IS_OWNER_ID, IS_OWNER_PW);
+ $mediaMapper = new Toolkit_Photos_Models_MediaMapper(
+ Toolkit_Database::getInstance()
+ );
+ $pos = $this->getCategoryMaxPos($values['catid']);
+ if (is_array($values['files']['name'])) {
+ for ($i = 0; $i < count($values['files']['name']); ++$i) {
+ // check that it's an image
+ // jpg jpeg gif or png
+ if ( !$values['files']['error'][$i]
+ && in_array($values['files']['type'][$i], $acceptedFiles)
+ ) {
+ $images[] = array(
+ 'name' => $values['files']['name'][$i],
+ 'tmp_name' => $values['files']['tmp_name'][$i],
+ 'size' => $values['files']['size'][$i]
+ );
+ }
+ }
+ }
+ if (!empty($images)) {
+ foreach ($images as $img) {
+ $imgData = $is->uploadImageFile($img['tmp_name']);
+ $photo = Toolkit_Photos_Models_Photo::createByValues(
+ array(
+ 'image' => $imgData['name'],
+ 'catid' => $values['catid']
+ )
+ );
+ $photoId = $mediaMapper->savePhoto($photo);
+ $photo2Category
+ = Toolkit_Photos_Models_Photo2Category::createByValues(
+ array(
+ 'photo' => $photoId,
+ 'category' => $values['catid'],
+ 'pos' => $pos
+ )
+ );
+ $mediaMapper->savePhoto2Category($photo2Category);
+ ++$pos;
+ }
+ }
+ }
+
+ /**
+ * Process folder
+ *
+ * @param array $values Values array
+ *
+ * @throws Exception
+ * @return void
+ * @access public
+ */
+ public function processFolder($values)
+ {
+ $is = new Toolkit_Image_Server();
+ $mediaMapper = new Toolkit_Photos_Models_MediaMapper(
+ Toolkit_Database::getInstance()
+ );
+ try {
+ if (!is_dir($_SESSION['uploadFolder'])) {
+ throw new Exception('No Folder exists');
+ }
+ } catch (Exception $e) {
+ Toolkit_Common::handleError($e);
+ }
+
+ $d = dir($_SESSION['uploadFolder']);
+ $pos = $this->getCategoryMaxPos($_REQUEST['catid']);
+ $i = 0;
+ while (false !== ($entry = $d->read())) {
+ if (!in_array($entry, array('.','..','.svn','CVS'))) {
+ // before we can send the image to the image class we need
+ // to inject the data for the images into the $_FILES array
+ $_FILES['img' . $i] = $this->getFileData($entry, $_SESSION['uploadFolder']);
+ // send to image server and insert values
+ $image_name = $is->imageUpload('img' . $i, $_SESSION['uploadFolder']);
+ $photo = Toolkit_Photos_Models_Photo::createByValues(
+ array(
+ 'image' => $image_name,
+ 'catid' => $_REQUEST['catid']
+ )
+ );
+ $photoId = $mediaMapper->savePhoto($photo);
+ $photo2Category
+ = Toolkit_Photos_Models_Photo2Category::createByValues(
+ array(
+ 'photo' => $photoId,
+ 'category' => $_REQUEST['catid'],
+ 'pos' => $pos
+ )
+ );
+ $mediaMapper->savePhoto2Category($photo2Category);
+ ++$pos;
+ unlink($_SESSION['uploadFolder'] . '/'. $entry);
+ ++$i;
+ }
+ }
+ $d->close();
+ if (is_dir($_SESSION['uploadFolder'])) {
+ rmdir($_SESSION['uploadFolder']);
+ }
+ }
+
+ // {{{ setupRenderers()
+ // @codeCoverageIgnoreStart
+
+ /**
+ * Custom rendering templates for special fields on the form
+ *
+ * @return void
+ * @access protected
+ */
+ protected function setupRenderers()
+ {
+ parent::setupRenderers();
+ $renderer =& $this->defaultRenderer();
+ $required = '<!-- BEGIN required --><span class="req"> * </span><!-- END required -->';
+ $error = '<!-- BEGIN error --><div class="req"> {error} </div><!-- END error -->';
+ }
+
+ // @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->cleanForm();
+ if ($this->process(array(&$this, 'processData'), $this->mergeFiles)) {
+ $this->freeze();
+ HTTP_Session2::unregister('uploadFolder');
+ header("Location: photos.php?ac=editCategory&id=" . $_REQUEST['catid']);
+ exit;
+ }
+
+ } elseif ($this->isSubmitted()) {
+ $output = $this->errorMsg;
+ $output .= parent::toHTML();
+ $output = '<pre>'.print_r($this, true).'</pre>';
+ } else {
+ $output = parent::toHTML();
+ }
+ return $output;
+ }
+
+ // }}}
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * PageTree.php
+ *
+ * PHP version 5.2
+ *
+ * @category Toolkit
+ * @package Blocks
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: (0.1)
+ * @link <>
+ */
+
+/**
+ * Toolkit_Package_PageTree
+ *
+ * Display the toolbox page as ul lil list for jQuery-Column viewer
+ *
+ * @category Toolkit
+ * @package Blocks
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @release Release: (0.1)
+ * @link <>
+ */
+class Toolkit_Photos_Admin_PageTree
+{
+ private $_dbh;
+ private $_rootNodeStart = "<ul class=\"menu\" id=\"demo1\">\n";
+ private $_leafStartExpanded = "\n\t<li class=\"expanded\" %s>\n";
+ private $_leafStartLeaf = "\n\t<li class=\"leaf\" %s>\n";
+ private $_subTreeStart = "\n<ul class=\"menu\">\n";
+ private $_treeEnd = "\n</ul>\n";
+ private $_leafEnd = "\n\t</li>\n";
+ private $_tree;
+
+ public function __construct(PDO $dbh)
+ {
+ $this->_dbh = $dbh;
+ }
+
+ /**
+ * creates and executes the sql query for getting the pages
+ *
+ * @return array | null
+ */
+ private function _findAll()
+ {
+ try {
+ $members
+ = (filter_var(MEMBERS_CATEGORY, FILTER_VALIDATE_INT))
+ ? "WHERE id NOT IN (" . MEMBERS_CATEGORY . ")
+ AND parent NOT IN (" . MEMBERS_CATEGORY . ")"
+ : '';
+ $sql = "
+ SELECT id,parent,navigation_name
+ FROM pages
+ $members
+ ORDER by parent, pos";
+
+ return $this->_dbh
+ ->query($sql)
+ ->fetchAll(PDO::FETCH_ASSOC);
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ /**
+ * Get all pages for the tree
+ *
+ * @return array
+ */
+ private function _fetchPages()
+ {
+ $pages = $this->_findAll();
+ if (is_array($pages)) {
+ $threads = array();
+ foreach ($pages as $page) {
+ $page['children'] = array();
+ $threads[] = $page;
+ }
+
+ $children = array();
+ while (list($key, $value) = each ($threads)) {
+ $children[$value['parent']][$value['id']] = $value;
+ }
+
+ $this->_tree = $children;
+ } else {
+ $this->_tree = array();
+ }
+ }
+
+ /**
+ * Create html of the pages tree for jqueyr.columnview
+ *
+ * @return string
+ */
+ public function toHtml()
+ {
+ $this->_fetchPages();
+ if (is_array($this->_tree)) {
+ $html = $this->createTree($this->_tree, reset($this->_tree));
+ }
+ return $html;
+ }
+
+ /**
+ * Creates the tree structure for the pages jquery column view
+ *
+ * @param array $tree Array for tree
+ * @param type $leaf Array for leaf
+ * @param type $level tree level
+ *
+ * @return string
+ */
+ protected function createTree(array $tree, $leaf, $level = 0)
+ {
+ $html = !$level ? $this->_rootNodeStart : $this->_subTreeStart;
+ if (is_array($leaf) && !empty($leaf)) {
+ while (list($parent, $branch) = each($leaf)) {
+ $pageName = htmlspecialchars($branch['navigation_name']);
+ if ($tree[$parent]) {
+ $html .= sprintf($this->_leafStartExpanded, null);
+ $html .= "<a href=\"#\" data-page=\"{$branch['id']}\" data-name=\"{$pageName}\">{$branch['navigation_name']} </a> ";
+ $html .= $this->createTree($tree, $tree[$parent], $level + 1);
+ } else {
+ $html .= sprintf($this->_leafStartLeaf, null);
+ $html .= "<a href=\"#\" data-page=\"{$branch['id']}\" data-name=\"{$pageName}\">{$branch['navigation_name']} </a> ";
+ $html .= $this->_leafEnd;
+ }
+ }
+ }
+ $html .= $this->_treeEnd;
+ if ($level) {
+ $html .= $this->_leafEnd;
+ }
+ return $html;
+ }
+}
--- /dev/null
+<?php
+// vim:set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker syntax=php:
+
+/**
+ * Member Authentication
+ *
+ * PHP version 5
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version CVS: $Id: Auth.php,v 1.22 2010/08/10 18:08:44 jamie Exp $
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit_Members_Auth-LoginForm, Toolkit_Members_Auth-PasswordForm
+ */
+
+require_once 'Auth.php';
+
+/**
+ * Methods for the memberdb authentication system
+ *
+ * Handles Cookie and session generation, id challenges and security for
+ * the memberdb application
+ *
+ * @category MembersDB
+ * @package Toolkit_Members
+ * @author Jamie Kahgee <jamie.kahgee@gmail.com>
+ * @copyright 2009 Jamie Kahgee
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ * @see Toolkit_Members_Auth-LoginForm, Toolkit_Members_Auth-PasswordForm
+ */
+class Toolkit_Photos_Auth extends Auth
+{
+ // {{{ properties
+
+ /**
+ * Maximum idle time
+ *
+ * If more seconds pass before a new page request, then the user
+ * will have to re-authenticate back into the application.
+ * 1800 = 30 min
+ * 3600 = 1 hr
+ *
+ * @var integer
+ * @access protected
+ */
+ protected $idleTime = 3600;
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * Sets up the storage driver
+ *
+ * @param Config_Container $c Configuration object
+ * @param Toolkit_Members_AuthContainer $storageDriver storage driver
+ * @param string $loginFunction (optional)Name of the function
+ * that creates the login form
+ * @param boolean $showLogin (optional)Should the login form
+ * be displayed if neccessary?
+ *
+ * @return void
+ * @access public
+ */
+ public function __construct(
+ Auth_Container $storageDriver,
+ $loginFunction = '',
+ $showLogin = false
+ ) {
+ parent::Auth($storageDriver, '', $loginFunction, $showLogin);
+ }
+
+ // }}}
+
+ // {{{ setIdle()
+
+ /**
+ * Set the maximum idle time
+ *
+ * @param integer $time time in seconds
+ * @param boolean $add (optional)add time to current maximum idle time or not
+ *
+ * @return void
+ * @access public
+ */
+ public function setIdle($time = null, $add = false)
+ {
+ $time = is_null($time) ? $this->idleTime : $time;
+ parent::setIdle($time, $add);
+ }
+
+ // }}}
+}
--- /dev/null
+<?php
+
+/**
+ * AuthContainer.php
+ *
+ * PHP version 5.3
+ *
+ * @category Toolkit
+ * @package Photos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: (0.1)
+ * @link <>
+ */
+
+/**
+ * Toolkit_Package_AuthContainer
+ *
+ * Description of AuthContainer
+ *
+ * @category Toolkit
+ * @package Photos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @release Release: (0.1)
+ * @link <>
+ */
+class Toolkit_Photos_AuthContainer
+ extends Auth_Container
+{
+ // {{{ properties
+
+ /**
+ * Database handler
+ * @var PDO
+ * @access private
+ */
+ private $_dbh;
+
+ /**
+ * Addition options for the storage container
+ * @var array
+ * @access private
+ */
+ private $_options = array();
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * @param PDO $dbh Database handler
+ *
+ * @return void
+ * @access public
+ */
+ public function __construct(PDO $dbh, array $options = null)
+ {
+ $this->_dbh = $dbh;
+ $this->_setDefaults();
+ if (is_array($options)) {
+ $this->_parseOptions($options);
+ }
+ }
+
+ // }}}
+ // {{{ _setDefaults()
+
+ /**
+ * Set some default options
+ *
+ * @access private
+ * @return void
+ */
+ private function _setDefaults()
+ {
+ $this->_options['sessionName'] = 'glmMedia';
+ $this->_options['table'] = 'contact';
+ $this->_options['usernamecol'] = 'email';
+ $this->_options['passwordcol'] = 'media_pass';
+ $this->_options['db_fields'] = array('id', 'fname', 'lname');
+ $this->_options['cryptType'] = 'none';
+ $this->_options['db_where'] = ' AND media = true AND approved = true'
+ . ' AND (expire IS NULL OR expire > current_date)';
+ }
+
+ // }}}
+ // {{{ _parseOptions()
+
+ /**
+ * Parse options passed to the container class
+ *
+ * @param array $array options for class
+ *
+ * @access private
+ * @return void
+ */
+ private function _parseOptions($array)
+ {
+ foreach ($array as $key => $value) {
+ if (isset($this->_options[$key])) {
+ $this->_options[$key] = $value;
+ }
+ }
+ }
+
+ // }}}
+ // {{{ fetchData()
+
+ /**
+ * Get the user information from the database
+ *
+ * @param string $username username to authenticate
+ * @param string $password password to authenticate against username
+ *
+ * @return boolean If the user was authenticated or not
+ * @access public
+ * @throws Toolkit_Members_Exception upon error querying DB for user
+ */
+ public function fetchData($username, $password)
+ {
+ if ( is_string($this->_options['db_fields'])
+ && strstr($this->_options['db_fields'], '*')
+ ) {
+ $sqlFrom = '*';
+ } else {
+ $sqlFrom = $this->_options['usernamecol'];
+
+ if (strlen($fields = $this->_getDBFields()) > 0) {
+ $sqlFrom .= ", $fields";
+ }
+
+ }
+
+ $pword = ($this->_options['cryptType'] == 'md5') ? 'MD5(:pword)' : ':pword';
+
+ $sql = "
+ SELECT $sqlFrom
+ FROM {$this->_options['table']}
+ WHERE {$this->_options['usernamecol']} = :uname
+ AND {$this->_options['passwordcol']} = $pword";
+
+ if ($this->_options['db_where']) {
+ $sql .= $this->_options['db_where'];
+ }
+
+ try {
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':uname', $username, PDO::PARAM_STR);
+ $stmt->bindParam(':pword', $password, PDO::PARAM_STR);
+ $stmt->execute();
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ if ($row !== FALSE) {
+ foreach ($row as $key => $value) {
+ $this->_auth_obj->setAuthData($key, $value);
+ }
+ return true;
+ }
+
+ return false;
+ } catch (PDOException $e) {
+ Toolkit_Logger::logException('DB Error', $e);
+ throw new Toolkit_Members_Exception(
+ "Error validating user `$username` - `$password`"
+ );
+ }
+ }
+
+ // }}}
+ // {{{ _getDBFields()
+
+ /**
+ * Get extra db fields to fetch and set in the auth data
+ *
+ * @return array comma separated string of extra db fields for a SQL query
+ * @access private
+ */
+ private function _getDBFields()
+ {
+ if (isset($this->_options['db_fields'])) {
+ if (is_array($this->_options['db_fields'])) {
+ return implode(', ', $this->_options['db_fields']);
+ }
+ }
+ }
+
+ // }}}
+}
+
--- /dev/null
+<?php
+
+/**
+ * IndexController.php
+ *
+ * PHP version 5.3
+ *
+ * @category Toolkit
+ * @package Media
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: (0.1)
+ * @link <>
+ */
+
+/**
+ * Toolkit_Package_IndexController
+ *
+ * Description of IndexController
+ *
+ * @category Toolkit
+ * @package Media
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @release Release: (0.1)
+ * @link <>
+ */
+class Toolkit_Photos_Controllers_IndexController
+ extends Toolkit_BaseControllerAbstract
+ implements Toolkit_IController
+{
+
+ const LIST_CATEGORY_TPL = 'Admin/listCategories.html';
+ const LIST_PHOTOS_TPL = 'Admin/listPhotos.html';
+ const LIST_USERS_TPL = 'Admin/listUsers.html';
+ const EDIT_CATEGORY_TPL = 'Admin/editCategory.html';
+ const EDIT_PHOTO_TPL = 'Admin/editPhoto.html';
+ const EDIT_USER_TPL = 'Admin/editUser.html';
+ const ADMIN_PAGE_TPL = 'Admin/index.html';
+
+ public function indexAction()
+ {
+ $pageUrl = $this->registry->page;
+ $flexyOptions = $this->registry->config->flexyOptions->toArray();
+ $tpl = new HTML_Template_Flexy($flexyOptions);
+ $tpl->compile(self::LIST_CATEGORY_TPL);
+ $mediaMapper = new Toolkit_Photos_Models_MediaMapper(
+ $this->registry->dbh
+ );
+ $page = new stdClass();
+ $page->imgPath = PHOTO_SMALL_URL;
+
+ // list template
+ $page->editUrl = $pageUrl . '?ac=editCategory&id=';
+ $page->deleteUrl = $pageUrl . '?ac=deleteCategory&id=';
+ $page->categories = $mediaMapper->fetchAllCategories();
+ return $this->_createPage($tpl->bufferedOutputObject($page));
+ }
+
+ public function ajaxPhotoSearchAction()
+ {
+ $jsonData = array();
+ $mediaMapper = new Toolkit_Photos_Models_MediaMapper(
+ $this->registry->dbh
+ );
+ $photoSearch = filter_var($_REQUEST['photoName'], FILTER_SANITIZE_STRING);
+ $photos = $mediaMapper->fetchPhotosByName(true);
+ if ($photos) {
+ foreach ($photos as $photo) {
+ $jsonData[] = $photo->getTitle();
+ }
+ }
+ return json_encode($jsonData);
+ }
+
+ public function multipleUploadAction()
+ {
+ define('PHOTOS_UPLOAD_PATH', BASE . 'uploads/photos/');
+
+ HTTP_Session2::useCookies(false);
+ HTTP_Session2::start('photoUploader');
+ $form = new Toolkit_Photos_Admin_FileUploader('file_upload_form');
+ $form->debug = YUI_UPLOADER_DEBUG;
+ $form->configureForm();
+ $formOut = $form->toHtml();
+ return $this->_createPage($formOut);
+ }
+
+ private function _createPage($html)
+ {
+ $GLOBALS['topScripts'][]
+ = MEDIA_APP_BASE_URL . 'libjs/jquery/jquery-1.7.2.min.js';
+ $GLOBALS['topScripts'][]
+ = MEDIA_BASE_URL . 'admin/Photos/checkBrowserSupport.js';
+ $GLOBALS['styleSheets'][]
+ = MEDIA_APP_BASE_URL . 'libjs/jqueryui/1.8.13/development-bundle/themes/base/jquery.ui.all.css';
+ $GLOBALS['styleSheets'][]
+ = MEDIA_BASE_URL . 'Toolkit/Photos/css/style.css';
+ $GLOBALS['styleSheets'][]
+ = MEDIA_BASE_URL . 'css/contactform.css';
+ $GLOBALS['topScripts'][]
+ = MEDIA_APP_BASE_URL . 'libjs/jqueryui/1.8.13/js/jquery-ui-1.8.13.custom.min.js';
+ $mediaMapper = new Toolkit_Photos_Models_MediaMapper(
+ $this->registry->dbh
+ );
+ $tpl = new HTML_Template_Flexy(
+ $this->registry->config->flexyOptions->toArray()
+ );
+ $page = new stdClass();
+ $ac = filter_var($_REQUEST['ac'], FILTER_SANITIZE_STRING);
+ $catId = filter_var($_REQUEST['id'], FILTER_VALIDATE_INT);
+ if ($ac && ($ac == 'editCategory') && $catId) {
+ $page->categoryId = $catId;
+ }
+
+ $page->categorySearchUrl
+ = MEDIA_BASE_URL . 'admin/photos.php';
+ $this->_setNav($page);
+ $page->topScripts = $this->_getTopScripts();
+ $page->bottomScripts = $this->_getBottomScripts();
+ $page->styles = $this->_getCss();
+ $page->categories = $mediaMapper->fetchAllCategories();
+ $page->AppName = $this->registry->config->application->name;
+ $page->content = $html;
+ $tpl->compile(self::ADMIN_PAGE_TPL);
+ return $tpl->bufferedOutputObject($page);
+ }
+
+ private function _setNav(&$page)
+ {
+ $page->userAdminUrl = MEDIA_BASE_URL . 'admin/photos.php';
+ $pageUrl = $this->registry->page;
+ $ac = filter_var($_REQUEST['ac'], FILTER_SANITIZE_STRING);
+
+ // navigation urls
+ if ($ac == 'editCategory') {
+ $catId = filter_var($_REQUEST['id'], FILTER_VALIDATE_INT);
+ if ($catId) {
+ $page->addPhotoUrl
+ = $pageUrl . '?ac=editPhoto&catid=' . $catId;
+ $page->addMultipleUrl
+ = $pageUrl . '?ac=multipleUpload&catid=' . $catId;
+ }
+ }
+ if ($ac == 'multipleUpload') {
+ $catId = filter_var($_REQUEST['catid'], FILTER_VALIDATE_INT);
+ if ($catId) {
+ $page->addPhotoUrl
+ = $pageUrl . '?ac=editPhoto&catid=' . $catId;
+ $page->addMultipleUrl
+ = $pageUrl . '?ac=multipleUpload&catid=' . $catId;
+ }
+ }
+ $page->addCategoryUrl = $pageUrl . '?ac=editCategory';
+ $page->listCategoryUrl = $pageUrl;
+ if ($this->registry->config->settings->mediaExclusive) {
+ $page->listUsersUrl = $pageUrl . '?ac=listUsers';
+ }
+ }
+
+ public function searchPhotosAction()
+ {
+ $mediaMapper = new Toolkit_Photos_Models_MediaMapper(
+ $this->registry->dbh
+ );
+ $flexyOptions
+ = $this->registry->config->flexyOptions->toArray();
+ $tpl
+ = new HTML_Template_Flexy($flexyOptions);
+ $page
+ = new stdClass();
+ $page->imgPath = PHOTO_SMALL_URL;
+ $page->photos = $mediaMapper->fetchPhotosByName();
+ $page->editUrl = $this->registry->page
+ . '?ac=editPhoto';
+ $this->_setNav($page);
+ $tpl->compile(self::LIST_PHOTOS_TPL);
+ return $this->_createPage($tpl->bufferedOutputObject($page));
+ }
+
+ public function listUsersAction()
+ {
+ $flexyOptions = $this->registry->config->flexyOptions->toArray();
+ $tpl = new HTML_Template_Flexy($flexyOptions);
+ $tpl->compile(self::LIST_USERS_TPL);
+ $mediaMapper = new Toolkit_Photos_Models_MediaMapper(
+ $this->registry->dbh
+ );
+ $page = new stdClass();
+ $this->_setNav($page);
+ $page->editUrl = $this->registry->page
+ . '?ac=editUser&catid=' . $catId
+ . '&id=';
+ $status = filter_var($_REQUEST['userStatus'], FILTER_SANITIZE_STRING);
+ $filters = array();
+ switch ($status) {
+ case 'approved':
+ $page->statusText = 'Approved';
+ $filters[] = "approved = true";
+ $filters[] = "(expire > current_date OR expire IS NULL)";
+ break;
+ case 'denied':
+ $page->statusText = 'Denied';
+ $filters[] = "denied = true";
+ break;
+ case 'expired':
+ $page->statusText = 'Expired';
+ $filters[] = "expire is not null";
+ $filters[] = "expire < current_date";
+ break;
+ default:
+ $page->statusText = 'Pending';
+ $filters[] = "((approved is null
+ AND denied IS NULL)
+ OR (denied = false AND approved = false))";
+ break;
+ }
+ $page->users = $mediaMapper->fetchUsers($filters);
+ return $this->_createPage($tpl->bufferedOutputObject($page));
+ }
+
+ public function showPagesAction()
+ {
+ $pageTree = new Toolkit_Photos_Admin_PageTree($this->registry->dbh);
+ return $pageTree->toHtml();
+ }
+
+ public function editCategoryAction()
+ {
+ $mediaMapper = new Toolkit_Photos_Models_MediaMapper(
+ $this->registry->dbh
+ );
+ if ($_POST) {
+ $saved = $mediaMapper->saveCategoryWithPost();
+ if ($saved) {
+ header('Location: ' . $this->registry->page);
+ exit;
+ }
+ }
+ $categoryId = filter_var($_REQUEST['id'], FILTER_VALIDATE_INT);
+
+ $GLOBALS['styleSheets'][]
+ = MEDIA_BASE_URL . 'css/contactform.css';
+ $GLOBALS['styleSheets'][]
+ = MEDIA_APP_BASE_URL
+ . 'libjs/jqueryui/1.8.13/development-bundle/themes/base/jquery.ui.all.css';
+ $GLOBALS['bottomScripts'][]
+ = MEDIA_BASE_URL . 'Toolkit/Photos/js/jquery.columnview.js';
+ $flexyOptions
+ = $this->registry->config->flexyOptions->toArray();
+ $tpl
+ = new HTML_Template_Flexy($flexyOptions);
+ $page
+ = new stdClass();
+ $page->mediaExclusive
+ = $this->registry->config->settings->mediaExclusive;
+ $page->slideShow
+ = $this->registry->config->settings->slideShowOption;
+ $page->pages2Categories
+ = ($categoryId)
+ ? $mediaMapper->fetchCategoryPages($categoryId)
+ : null;
+ $page->imgPath = PHOTO_SMALL_URL;
+ $page->photos
+ = ($categoryId)
+ ? $mediaMapper->fetchAllPhotosByCatid($categoryId)
+ : null;
+ $page->categoryId = $categoryId;
+ $page->editUrl = $this->registry->page
+ . '?ac=editPhoto&catid=' . $categoryId
+ . '&id=';
+ $this->_setNav($page);
+ if ($categoryId) {
+ $page->category = $mediaMapper->fetchCategoryById($categoryId);
+ }
+ $page->formAction = $this->registry->page . '?ac=editCategory';
+ $tpl->compile(self::EDIT_CATEGORY_TPL);
+ return $this->_createPage($tpl->bufferedOutputObject($page));
+ }
+
+ public function editPhotoAction()
+ {
+ $mediaMapper = new Toolkit_Photos_Models_MediaMapper(
+ $this->registry->dbh
+ );
+ $catId = filter_var($_REQUEST['catid'], FILTER_VALIDATE_INT);
+ // grab the category
+ if ($catId) {
+ $photoCategory = $mediaMapper->fetchCategoryById($catId);
+ }
+ $pageUrl = $this->registry->page;
+
+ if ($_POST) {
+ $saved = $mediaMapper->savePhotoWithPost();
+ if ($saved) {
+ header('Location: '
+ . $this->registry->page.'?ac=editCategory&id='
+ . $catId);
+ exit;
+ }
+ exit;
+ }
+ $photoId = filter_var($_REQUEST['id'], FILTER_VALIDATE_INT);
+
+ $GLOBALS['styleSheets'][]
+ = MEDIA_BASE_URL . 'css/contactform.css';
+ $GLOBALS['styleSheets'][]
+ = MEDIA_APP_BASE_URL . 'libjs/plugins/asmselect/1.0.4a/jquery.asmselect.css';
+ $GLOBALS['bottomScripts'][]
+ = MEDIA_APP_BASE_URL . 'libjs/plugins/asmselect/1.0.4a/jquery.asmselect.js';
+ $flexyOptions = $this->registry->config->flexyOptions->toArray();
+ $tpl = new HTML_Template_Flexy($flexyOptions);
+ $page = new stdClass();
+ $page->mediaExclusive
+ = $this->registry->config->settings->mediaExclusive;
+ $page->catid = $catId;
+ $page->photo2Categories
+ = ($photoId)
+ ? $mediaMapper->fetchPhoto2CategoryByPhotoId($photoId)
+ : new ArrayObject();
+ $page->imgPath = PHOTO_SMALL_URL;
+ $page->categoryName= $photoCategory->getCategory();
+ $this->_setNav($page);
+ if ($photoId) {
+ $page->photo = $mediaMapper->fetchPhotoById($photoId);
+ }
+ $page->categories = $mediaMapper->fetchAllCategories();
+ $page->formAction = $this->registry->page
+ . '?ac=editPhoto&catid=' . $catId;
+ $tpl->compile(self::EDIT_PHOTO_TPL);
+ return $this->_createPage($tpl->bufferedOutputObject($page));
+ }
+
+ public function editUserAction()
+ {
+ $GLOBALS['styleSheets'][] = MEDIA_BASE_URL . 'css/contactform.css';
+ $pageUrl = $this->registry->page;
+ $mediaMapper = new Toolkit_Photos_Models_MediaMapper(
+ $this->registry->dbh
+ );
+ if ($_POST) {
+ // if the user is beign approved
+ if ($_REQUEST['status'] == 'approved') {
+ // expire date needs to be greater or equal to current date
+ $expire = filter_var(
+ $_REQUEST['expire'],
+ FILTER_VALIDATE_REGEXP,
+ array(
+ 'options' => array(
+ 'regexp' => '%[0-9]{2}/[0-9]{2}/[0-9]{4}%'
+ )
+ )
+ );
+ $isActiveDate
+ = (!$expire || strtotime($expire) >= mktime());
+ if ($isActiveDate) {
+ $this->emailUser('approved');
+ }
+ }
+ // if the user is being denied
+ if ($_REQUEST['status'] == 'denied') {
+ $this->emailUser('denied');
+ }
+
+ $saved = $mediaMapper->saveUserWithPost();
+ if ($saved) {
+ $status = filter_var(
+ $_REQUEST['userStatus'], FILTER_SANITIZE_STRING
+ );
+ header(
+ 'Location: ' . $this->registry->page.'?ac=listUsers'
+ . '&userStatus=' . $status
+ );
+ exit;
+ }
+ exit;
+ }
+ $userId
+ = filter_var($_REQUEST['id'], FILTER_VALIDATE_INT);
+ $flexyOptions
+ = $this->registry->config->flexyOptions->toArray();
+ $tpl = new HTML_Template_Flexy($flexyOptions);
+ $page = new stdClass();
+ $this->_setNav($page);
+ if ($userId) {
+ $page->user = $mediaMapper->fetchUserById($userId);
+ }
+ $page->formAction = $this->registry->page . '?ac=editUser';
+ $tpl->compile(self::EDIT_USER_TPL);
+ return $this->_createPage($tpl->bufferedOutputObject($page));
+ }
+
+ public function emailUser($status)
+ {
+ $userId
+ = filter_var($_REQUEST['id'], FILTER_VALIDATE_INT);
+ $mediaMapper = new Toolkit_Photos_Models_MediaMapper(
+ $this->registry->dbh
+ );
+ $page = new stdClass();
+ $page->user = $mediaMapper->fetchUserById($userId);
+ if (!$page->user instanceof Toolkit_Photos_Models_User) {
+ return false;
+ }
+ if (!$page->user->getEmail()) {
+ return false;
+ }
+ $page->title = SITENAME . ' Media Gallery';
+ $page->subject = 'Your Media Request for Photos - Traverse City';
+ $page->email_from = MEDIA_REQUEST_FORM_EMAIL;
+ switch ($status) {
+ case 'approved' :
+ $page->approved = true;
+ break;
+ case 'denied' :
+ $page->denied = true;
+ break;
+ default :
+ return false;
+ }
+ $flexyOptions = $GLOBALS['flexyOptions'];
+ $flexyOptions['templateDir'] = BASE . 'Toolkit/Photos/templates/Admin';
+ $flexyOptions['compileDir'] = BASE . 'Toolkit/Photos/templates/compiled';
+ $tpl = new HTML_Template_Flexy($flexyOptions);
+ $tpl->compile('emailUser.tpl');
+ $htmlMsg = $tpl->bufferedOutputObject($page);
+ $msg = strip_tags($htmlMsg);
+ $mimeMail = new Mail_mime("\n");
+ $mimeMail->setFrom("Traverse City Media Gallery <".MEDIA_REQUEST_FORM_EMAIL.">");
+ $mimeMail->setSubject($page->subject);
+ $mimeMail->setHTMLBody($htmlMsg);
+ $mimeMail->setTXTBody($msg);
+
+ $mail =& Mail::factory('mail');
+ $body = $mimeMail->get();
+ $setHeader['Reply-To'] = "Traverse City Media Gallery <".MEDIA_REQUEST_FORM_EMAIL.">";
+
+ $headers = $mimeMail->headers($setHeader);
+
+ $res = $mail->send($page->user->getEmail(), $headers, $body);
+ if (PEAR::isError($res)) {
+ return Toolkit_Common::handleError($res);
+ } else {
+ return $res;
+ }
+ exit;
+ }
+
+ public function moveCategoriesAction()
+ {
+ $mediaMapper = new Toolkit_Photos_Models_MediaMapper(
+ $this->registry->dbh
+ );
+ $values = filter_var_array(
+ $_REQUEST,
+ array(
+ 'catPhotos' => array(
+ 'filter' => FILTER_VALIDATE_INT,
+ 'flags' => FILTER_FORCE_ARRAY
+ )
+ )
+ );
+ if ($values['catPhotos']) {
+ $mediaMapper->saveCategoryPositionsByArray($values['catPhotos']);
+ }
+ return true;
+ }
+
+ public function movePhotosAction()
+ {
+ $categoryId = filter_var($_REQUEST['categoryId'], FILTER_VALIDATE_INT);
+ if (!$categoryId) {
+ return false;
+ }
+ $mediaMapper = new Toolkit_Photos_Models_MediaMapper(
+ $this->registry->dbh
+ );
+ $values = filter_var_array(
+ $_REQUEST,
+ array(
+ 'categoryId' => FILTER_VALIDATE_INT,
+ 'photos' => array(
+ 'filter' => FILTER_VALIDATE_INT,
+ 'flags' => FILTER_FORCE_ARRAY
+ )
+ )
+ );
+ if ($values['photos']) {
+ $mediaMapper->savePhotoPositionsByCategory(
+ $values['photos'],
+ $values['categoryId']
+ );
+ }
+ return '<pre>'.print_r($photo2categories, true).'</pre>';
+ }
+
+ private function _getCss()
+ {
+ return Toolkit_Common::getStyleSheets();
+ }
+
+ private function _getTopScripts()
+ {
+ return Toolkit_Common::getScripts($GLOBALS['topScripts']);
+ }
+
+ private function _getBottomScripts()
+ {
+ return Toolkit_Common::getScripts($GLOBALS['bottomScripts']);
+ }
+
+}
--- /dev/null
+--
+-- adding slideshow
+--
+
+ALTER TABLE photos.photo_category ADD slideshow BOOLEAN;
+ALTER TABLE photos.photo_category ALTER slideshow SET DEFAULT false;
+UPDATE photos.photo_category SET slideshow = false;
--- /dev/null
+CREATE SCHEMA photos;
+GRANT ALL ON SCHEMA photos TO nobody;
+--
+-- Tables
+--
+\i ./tables/photo_category.sql
+\i ./tables/photo.sql
+\i ./tables/photo_category_bus.sql
+\i ./tables/photo_default.sql
+\i ./tables/photo2category.sql
--- /dev/null
+--
+-- This will drop everything in the photos schema.
+-- Nothing better be in here except photos related objects
+-- or it will be dropped
+--
+-- The force is strong w/ this one, use it wisely.
+--
+DROP SCHEMA IF EXISTS photos CASCADE;
--- /dev/null
+--
+-- Need to reset sequences for photos tables
+-- try running this file
+--
+SET search_path TO photos;
+SELECT setval('photo_id_seq', (SELECT max(id) FROM photos.photo));
+SELECT setval('photo_category_id_seq', (SELECT max(id) FROM photos.photo_category));
\ No newline at end of file
--- /dev/null
+DROP TABLE IF EXISTS photos.photo CASCADE;
+
+CREATE TABLE photos.photo
+(id SERIAL,
+ title TEXT,
+ description TEXT,
+ image TEXT,
+ catid INTEGER NOT NULL
+ REFERENCES photos.photo_category (id)
+ ON UPDATE CASCADE
+ ON DELETE CASCADE,
+ pos INTEGER,
+ exclusive BOOLEAN DEFAULT false,
+ download BOOLEAN DEFAULT false,
+ PRIMARY KEY (id));
+
+GRANT ALL on photos.photo_id_seq to nobody;
+GRANT ALL on photos.photo to nobody;
--- /dev/null
+DROP TABLE IF EXISTS photos.photo2category CASCADE;
+
+CREATE TABLE photos.photo2category
+(
+ id SERIAL,
+ photo INTEGER,
+ category INTEGER,
+ pos INTEGER,
+ PRIMARY KEY (id)
+);
+
+GRANT ALL ON photos.photo2category TO nobody;
+GRANT ALL ON photos.photo2category_id_seq TO nobody;
\ No newline at end of file
--- /dev/null
+DROP TABLE IF EXISTS photos.photo_category CASCADE;
+
+CREATE TABLE photos.photo_category
+(id SERIAL,
+ category TEXT,
+ image TEXT,
+ pos INTEGER,
+ exclusive BOOLEAN DEFAULT false,
+ slideshow BOOLEAN DEFAULT false,
+ PRIMARY KEY (id));
+
+GRANT ALL ON photos.photo_category_id_seq TO nobody;
+GRANT ALL ON photos.photo_category TO nobody;
--- /dev/null
+DROP TABLE IF EXISTS photos.photo_category_bus CASCADE;
+
+CREATE TABLE photos.photo_category_bus
+(id SERIAL,
+ photocat_id INTEGER
+ REFERENCES photos.photo_category (id)
+ ON UPDATE CASCADE
+ ON DELETE CASCADE,
+ buscat_id INTEGER
+ REFERENCES toolbox.pages (id)
+ ON UPDATE CASCADE
+ ON DELETE CASCADE,
+ pos INTEGER,
+ PRIMARY KEY (id)
+);
+
+GRANT ALL ON photos.photo_category_bus_id_seq TO nobody;
+GRANT ALL ON photos.photo_category_bus TO nobody;
+
+CREATE UNIQUE INDEX photo_category_bus_bus_phot_indx on photos.photo_category_bus (buscat_id ,photocat_id);
--- /dev/null
+DROP TABLE IF EXISTS photos.photo_default CASCADE;
+
+CREATE TABLE photos.photo_default
+(id SERIAL,
+ header TEXT,
+ description TEXT,
+ PRIMARY KEY (id));
+
+GRANT ALL ON photos.photo_default_id_seq TO nobody;
+GRANT ALL ON photos.photo_default TO nobody;
--- /dev/null
+--
+-- Update photo tables
+--
+
+\i ./tables/photo2category.sql
+
+ALTER TABLE photos.photo_category ALTER pos SET DEFAULT 1;
+ALTER TABLE photos.photo_category ADD exclusive bool;
+ALTER TABLE photos.photo_category ALTER exclusive set default false;
+UPDATE photos.photo_category SET exclusive = false;
+
+ALTER TABLE photos.photo add exclusive bool;
+ALTER TABLE photos.photo ALTER exclusive set default false;
+UPDATE photos.photo SET exclusive = false;
+
+ALTER TABLE photos.photo add download bool;
+ALTER TABLE photos.photo ALTER download set default false;
+UPDATE photos.photo SET download = false;
+
+ALTER TABLE contacts.contact ADD title TEXT;
\ No newline at end of file
--- /dev/null
+--
+-- Upgrade (movie schemas)
+--
+
+CREATE SCHEMA oldphotos;
+GRANT ALL ON oldphotos TO nobody;
+
+ALTER TABLE public.photo SET SCHEMA oldphotos;
+ALTER TABLE public.photo_category SET SCHEMA oldphotos;
+ALTER TABLE public.photo_category_bus SET SCHEMA oldphotos;
+ALTER TABLE public.photo_default SET SCHEMA oldphotos;
+
+INSERT INTO photos.photo_category (SELECT * FROM oldphotos.photo_category);
+INSERT INTO photos.photo (SELECT * FROM oldphotos.photo);
+INSERT INTO photos.photo_category_bus (SELECT * FROM oldphotos.photo_category_bus);
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Display.php
+ *
+ * PHP version 5
+ *
+ * @category Photos
+ * @package Toolkit_Photos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2009 Gaslight Media
+ * @license Gaslight Media
+ * @version CVS: $Id: Display.php,v 1.10 2010/07/04 23:55:12 jamie Exp $
+ * @link <>
+ */
+
+/**
+ * Toolkit_Photos_Display
+ *
+ * Display the Photo Gallery assoc to a toolbox page
+ *
+ * @category Photos
+ * @package Toolkit_Photos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2009 Gaslight Media
+ * @license Gaslight Media
+ * @link <>
+ */
+class Toolkit_Photos_Display
+{
+ // {{{ Properties
+
+ private $_dbh;
+
+ /**
+ * Options for Flexy Templates
+ * @var array
+ * @access protected
+ */
+ protected $flexyOptions;
+
+ /**
+ * page name for form action and links
+ * @var unknown
+ * @access protected
+ */
+ protected $pageName;
+
+ /**
+ * Photo Table Name
+ * @var string
+ * @access protected
+ */
+ protected $photoTable = 'photo';
+
+ /**
+ * Photo Category Table Name
+ * @var string
+ * @access protected
+ */
+ protected $categoryTable = 'photo_category';
+
+ /**
+ * rowCount
+ *
+ * @var float
+ * @access protected
+ */
+ protected $rowCount = 4;
+ protected $baseURL;
+ protected $glmAppBaseURL;
+ protected $pageId;
+ protected $config;
+
+ const PHOTO_GALLERY_WRAPPER_TPL = 'photoGalleryWrapper.html';
+ const PHOTO_SLIDER = 'photoSlider.html';
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * __construct()
+ *
+ * @return void
+ * @access public
+ */
+ function __construct(PDO $dbh)
+ {
+ $this->pageId = filter_var($_REQUEST['catid'], FILTER_VALIDATE_INT);
+ $this->_dbh = $dbh;
+ // create a Zend Config Object and store into Registry
+ $config = new Zend_Config_Ini(
+ BASE . 'Toolkit/Photos/application.ini',
+ strtolower($_ENV['GLM_HOST_ID'])
+ );
+ $this->config = $config;
+ $this->flexyOptions = $config->flexyOptions->toArray();
+
+ // the main display page for events to link to
+ $this->pageName = BASE_URL . 'index.php?catid=' . $_REQUEST['catid'];
+ $this->baseURL = ($_SERVER['HTTPS'] == 'on')
+ ? BASE_SECURE_URL
+ : BASE_URL;
+ $this->glmAppBaseURL = ($_SERVER['HTTPS'] == 'on')
+ ? GLM_APP_BASE_SECURE_URL
+ : GLM_APP_BASE_URL;
+ }
+
+ // }}}
+ public function getSlideShow(array $photoCatIds, $galleries)
+ {
+ $GLOBALS['styleSheets'][] = $this->glmAppBaseURL
+ . 'libjs/plugins/nivoslider/3.2/prod/nivo-slider.css';
+ $GLOBALS['styleSheets'][] = $this->glmAppBaseURL
+ . 'libjs/plugins/nivoslider/themes/default/default.css';
+ $GLOBALS['bottomScripts'][] = $this->glmAppBaseURL
+ . 'libjs/plugins/nivoslider/3.2/prod/jquery.nivo.slider.js';
+ $tpl = new HTML_Template_Flexy($this->flexyOptions);
+ $tpl->compile(self::PHOTO_SLIDER);
+
+ $page = new stdClass();
+
+ // Filter the categories so only slideshow ones are in $categories
+ $categories = $this->getCategories($photoCatIds);
+ $iterator = new Toolkit_Photos_SlideShowCategoryFilter(
+ $categories->getIterator()
+ );
+ $slideShowCategories = new ArrayObject();
+ $photoCatIds = array();
+ foreach ($iterator as $index) {
+ $slideShowCategories->append($index);
+ $photoCatIds[] = $index['id'];
+ }
+ if (empty($photoCatIds)) {
+ return false;
+ }
+
+ $page->categories = $slideShowCategories;
+ $page->searchFormUrl = $this->pageName;
+ $page->pageId = $this->pageId;
+ $page->base_url = BASE_URL;
+ $page->webUrl = BASE_URL . 'download-photo-web/';
+ $page->printUrl = BASE_URL . 'download-photo-print/';
+ $page->photoUrlLarge = FILE_SERVER_URL . IS_OWNER_ID
+ . '/rotatingImagesResized/';
+ $page->photoUrlSmall = FILE_SERVER_URL . IS_OWNER_ID
+ . '/mediaGallery/';
+ $catid = filter_var($_REQUEST['photoCategoryId']);
+
+ if (count($page->categories) == 1) {
+ $catid = $photoCatIds[0];
+ }
+ $photoCatSelected = ($catid)
+ ? $catid
+ : $photoCatIds[0];
+ $page->photos = $this->getPhotosByCatid(
+ $photoCatSelected,
+ $this->getLoginStatus()
+ );
+
+
+ return $tpl->bufferedOutputObject($page);
+ }
+ // {{{ toHTML()
+
+ /**
+ * toHTML()
+ *
+ * call to listPhotos function for display of Photos
+ *
+ * @return void
+ * @access public
+ */
+ public function toHTML(array $photoCatIds, $galleries)
+ {
+ $GLOBALS['styleSheets'][]
+ = $this->baseURL . 'photoswipe/photoswipe.css';
+ $GLOBALS['styleSheets'][]
+ = $this->baseURL . 'Toolkit/Photos/css/gallery.css';
+ $GLOBALS['bottomScripts'][]
+ = $this->baseURL . 'photoswipe/lib/klass.min.js';
+ $GLOBALS['bottomScripts'][]
+ = $this->baseURL . 'photoswipe/code.photoswipe.jquery-3.0.5.js';
+ $GLOBALS['bottomScripts'][]
+ = $this->baseURL . 'Toolkit/Photos/js/photoGallery.js';
+
+ $GLOBALS['styleSheets'][] = $this->glmAppBaseURL
+ . 'libjs/jqueryui/1.8.13/development-bundle/themes/base/jquery.ui.all.css';
+ $GLOBALS['styleSheets'][] = $this->baseURL
+ . 'Toolkit/Photos/css/style.css';
+ $GLOBALS['styleSheets'][] = $this->baseURL
+ . 'css/contactform.css';
+ $GLOBALS['topScripts'][] = $this->glmAppBaseURL
+ . 'libjs/jqueryui/1.8.13/js/jquery-ui-1.8.13.custom.min.js';
+
+ $tpl = new HTML_Template_Flexy($this->flexyOptions);
+ $tpl->compile(self::PHOTO_GALLERY_WRAPPER_TPL);
+
+ $page = new stdClass();
+ $page->mediaExclusive = $this->config->settings->mediaExclusive;
+ $page->photoNameSearch = $this->config->settings->photoNameSearch;
+ $page->galleries = $galleries;
+ $page->pageId = $this->pageId;
+ $page->base_url = BASE_URL;
+ $page->mediaGalleryRequestFormUrl = BASE_URL . 'media-gallery-request-form-'
+ . MEDIA_GALLERY_REQUEST_FORM . '/';
+ $page->isLoggedIn = $this->getLoginStatus();
+ $page->loginUrl = BASE_URL . 'Toolkit/Photos/login.php';
+ $page->logoutUrl = BASE_URL . 'Toolkit/Photos/login.php?catid='
+ . $_REQUEST['catid'] . '&logout=1';
+ $page->photoSearchFormUrl = $this->pageName;
+ $page->photoUrlLarge = PHOTO_LARGE_URL;
+ $page->photoUrlSmall = FILE_SERVER_URL . IS_OWNER_ID . '/mediaGallery/';
+ $page->photoDownWeb = BASE_URL . "download-photo-web/";
+ $page->photoDownPrint = BASE_URL . "download-photo-print/";
+
+ // Filter out the slideshow categories
+ $categories = $this->getCategories($photoCatIds);
+ $iterator = new Toolkit_Photos_GalleryCategoryFilter(
+ $categories->getIterator()
+ );
+ $galleryCategories = new ArrayObject();
+ $photoCatIds = array();
+ foreach ($iterator as $index) {
+ $galleryCategories->append($index);
+ $photoCatIds[] = $index['id'];
+ }
+ if (empty($photoCatIds)) {
+ return false;
+ }
+ $page->categories = $galleryCategories;
+
+ $failedStatus = $this->_getFailedLoginStatus();
+ $page->expired = false;
+ if ($failedStatus == -4) {
+ $page->failedStatus = '';
+ $page->expired = true;
+ } else {
+ $page->failedStatus = $failedStatus;
+ }
+
+ $catid = filter_var($_REQUEST['photoCategoryId'], FILTER_VALIDATE_INT);
+ $photoName = filter_var($_REQUEST['photo_name'], FILTER_SANITIZE_STRING);
+
+ if (count($page->categories) == 1) {
+ $catid = $photoCatIds[0];
+ }
+ if ($photoName) {
+ $mediaMapper = new Toolkit_Photos_Models_MediaMapper(
+ $this->_dbh
+ );
+ $gallery = new Toolkit_Photos_Gallery(
+ Toolkit_Database::getInstance(),
+ new Toolkit_Photos_Display(
+ Toolkit_Database::getInstance()
+ )
+ );
+ $page->photos = $mediaMapper->fetchPhotosByNameAndCats(
+ $photoName, $gallery->getPageGalleries($this->pageId)
+ );
+ } else if ($catid) {
+ $photoCatSelected = ($catid)
+ ? $catid
+ : $photoCatIds[0];
+ $photoCategory = $this->getPhotoCategory($photoCatSelected);
+ $page->photoCategoryName = $photoCategory['category'];
+ $page->photos = $this->getPhotosByCatid(
+ $photoCatSelected, $page->isLoggedIn
+ );
+ } else {
+ $page->photoUrl = $this->pageName . '&photoCategoryId=';
+ $page->catPhotos = $this->getCategoriesForPage($photoCatIds);
+ }
+
+ return $tpl->bufferedOutputObject($page);
+ }
+
+ // }}}
+
+ public function getLoginStatus()
+ {
+ $authContainer = new Toolkit_Photos_AuthContainer(
+ Toolkit_Database::getInstance()
+ );
+
+ $photoAuth = new Toolkit_Photos_Auth(
+ $authContainer, '', false
+ );
+ $photoAuth->start();
+ return $photoAuth->checkAuth();
+ }
+
+ private function _getFailedLoginStatus()
+ {
+ $failStatus = filter_var($_REQUEST['status'], FILTER_VALIDATE_INT);
+ switch ($failStatus) {
+ case -1:
+ $status = 'Idled';
+ break;
+ case -2:
+ $status = 'Expired';
+ break;
+ case -3:
+ $status = 'Incorrect Username/Password supplied';
+ break;
+ case -4:
+ return -4;
+ $url = BASE_URL . 'media-gallery-request-form-'
+ . MEDIA_GALLERY_REQUEST_FORM . '/';
+ $status = 'Your login has expired';
+ $status .= ' <a href="' . $url . '">Ask for more time</a>';
+ break;
+ default:
+ $status = '';
+ break;
+ }
+ return $status;
+ }
+
+ public function getPhotosByCatid($catid, $isLogedIn)
+ {
+ $filter = (!$isLogedIn)
+ ? array("exclusive <> true")
+ : '';
+
+ $mediaMapper = new Toolkit_Photos_Models_MediaMapper(
+ $this->_dbh
+ );
+ $photos = $mediaMapper->fetchAllPhotosByCatid(
+ $catid, $filter
+ );
+ return $photos;
+ }
+
+ public function getCategoriesForPage($photoCats)
+ {
+ $categories = new ArrayObject();
+ $mediaMapper = new Toolkit_Photos_Models_MediaMapper(
+ $this->_dbh
+ );
+ if (is_array($photoCats) && !empty($photoCats)) {
+ $index = 0;
+ foreach ($photoCats as $cat) {
+ $categories->offsetSet(
+ $index, $mediaMapper->fetchCategoryById($cat)
+ );
+ ++$index;
+ }
+ }
+ return $categories;
+ }
+
+ public function getCategories($photoCats)
+ {
+ $categories = new ArrayObject();
+ if (is_array($photoCats) && !empty($photoCats)) {
+ $index = 0;
+ foreach ($photoCats as $cat) {
+ $categories->offsetSet(
+ $index, $this->getPhotoCategory($cat)
+ );
+ ++$index;
+ }
+ }
+ return $categories;
+ }
+
+ public function getPhotoCategory($categoryId)
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM photos.photo_category
+ WHERE id = :id
+ ORDER BY pos";
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':id', $categoryId, PDO::PARAM_INT);
+ $stmt->execute();
+ return $stmt->fetch(PDO::FETCH_ASSOC);
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+}
--- /dev/null
+<?php
+class Toolkit_Photos_Exception extends Exception {}
+?>
--- /dev/null
+<?php
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/**
+ * Description of Factory
+ *
+ * @author steve
+ */
+class Toolkit_Photos_Factory
+{
+ static public function createPhotoFromValues($values)
+ {
+ $newPhoto = new Toolkit_Photos_Photo();
+ $photo = $newPhoto->createByValues($values);
+ return $photo;
+ }
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * Fetches photo galleries assigned to pages
+ *
+ * PHP version 5
+ *
+ * The license text...
+ *
+ * @category Toolkit_Photos
+ * @package Photos
+ * @author Jamie Kahgee <jamie@gaslightmedia.com>
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version CVS: $Id: Gallery.php,v 1.1 2010/06/09 19:52:24 jamie Exp $
+ * @link <>
+ * @see References to other sections (if any)...
+ */
+
+/**
+ * Fetches photo galleries assigned to pages
+ *
+ * @category Toolkit_Photos
+ * @package Photos
+ * @author Jamie Kahgee <jamie@gaslightmedia.com>
+ * @copyright 2010 Jamie Kahgee
+ * @license http://www.gaslightmedia.com/ Gaslightmedia
+ * @version Release: @package_version@
+ * @link <>
+ * @see References to other sections (if any)...
+ */
+class Toolkit_Photos_Gallery
+{
+ // {{{ properties
+
+ /**
+ * Database handler
+ * @var object
+ * @access private
+ */
+ private $_dbh;
+
+ /**
+ * Toolkit_Photos_Display object
+ * @var object
+ * @access private
+ */
+ private $_photoApp;
+
+ // }}}
+ // {{{ __construct()
+
+ /**
+ * Constructor
+ *
+ * @param PDO $dbh Database handler
+ * @param Toolkit_Photos_Display $photoApp Photo Gallery Display object
+ * @return void
+ * @access public
+ */
+ public function __construct(PDO $dbh, Toolkit_Photos_Display $photoApp)
+ {
+ $this->_dbh = $dbh;
+ $this->_photoApp = $photoApp;
+ }
+
+ // }}}
+ // {{{ _getGalleriesAssignedToPage()
+
+ /**
+ * Gets an array of photo galleries assigned to page
+ *
+ * If we were on a page that contained multiple galleries
+ * and we move into a single gallery page - this function
+ * returns that single gallery, so we can view all its photos
+ *
+ * @param integer $pageId Id of page we're on
+ *
+ * @return array multi-dimensional array of photo galleries assigned to page
+ * @access private
+ * @throws Toolkit_Photos_Exception If can't query for galleries on page
+ */
+ private function _getGalleriesAssignedToPage($pageId)
+ {
+ if (isset($_GET['photo_catid']) && ctype_digit($_GET['photo_catid'])) {
+ return array(
+ array('photocat_id' => $_GET['photo_catid'])
+ );
+ }
+
+ try {
+ $where
+ = (!$this->_photoApp->getLoginStatus())
+ ? " AND exclusive <> true"
+ : '';
+ $sql = "
+ SELECT pcb.photocat_id
+ FROM photo_category_bus pcb, photo_category pc
+ WHERE buscat_id = :pageId
+ AND pc.id = pcb.photocat_id
+ AND pc.id IN (
+ SELECT distinct category
+ FROM photo2category
+ )
+ $where
+ ORDER BY pc.pos";
+
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':pageId', $pageId, PDO::PARAM_INT);
+ $stmt->execute();
+ return $stmt->fetchAll(PDO::FETCH_ASSOC);
+ } catch (PDOException $e) {
+ Toolkit_Logger::logException('DB Error', $e);
+ throw new Toolkit_Photos_Exception(
+ "Unable to check if page has a gallery `$pageId`"
+ );
+ }
+ }
+
+ // }}}
+ public function getPageGalleries($pageId)
+ {
+ $cats = array();
+ $galleries = $this->_getGalleriesAssignedToPage($pageId);
+ foreach ($galleries as $galley) {
+ $cats[] = $galley['photocat_id'];
+ }
+ return $cats;
+ }
+ // {{{ getPageGallery()
+
+ /**
+ * Gets the page galleries / gallery
+ *
+ * @param integer $pageId Id of page we're on
+ *
+ * @return string photo gallery output
+ * @access public
+ */
+ public function getPageGallery($pageId)
+ {
+ $galleries = $this->_getGalleriesAssignedToPage($pageId);
+
+ $photoCatIds = array();
+ foreach ($galleries as $gallery) {
+ $photoCatIds[] = $gallery['photocat_id'];
+ }
+
+ return !empty($photoCatIds)
+ ? $this->_photoApp->toHTML($photoCatIds, $galleries)
+ : '';
+ }
+
+ // }}}
+
+ public function getPageSlideShow($pageId)
+ {
+ $galleries = $this->_getGalleriesAssignedToPage($pageId);
+
+ $photoCatIds = array();
+ foreach ($galleries as $gallery) {
+ $photoCatIds[] = $gallery['photocat_id'];
+ }
+
+ return !empty($photoCatIds)
+ ? $this->_photoApp->getSlideShow($photoCatIds, $galleries)
+ : '';
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * GalleryCategoryFilter.php
+ *
+ * PHP version 5.3
+ *
+ * @category Toolkit
+ * @package Photos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: (0.1)
+ * @link <>
+ */
+
+/**
+ * Toolkit_Photos_GalleryCategoryFilter
+ *
+ * Description of SlideShowFilter
+ *
+ * @category Toolkit
+ * @package Photos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @release Release: (0.1)
+ * @link <>
+ */
+class Toolkit_Photos_GalleryCategoryFilter
+ extends FilterIterator
+{
+ public function __construct(Iterator $iterator)
+ {
+ parent::__construct($iterator);
+ }
+
+ public function accept()
+ {
+ $category = $this->getInnerIterator()->current();
+ if (!$category['slideshow']) {
+ return true;
+ }
+ return false;
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Category.php
+ *
+ * PHP version 5.3
+ *
+ * @category Toolkit
+ * @package Media
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: (0.1)
+ * @link <>
+ */
+
+/**
+ * Toolkit_Photos_Models_Category
+ *
+ * Represents the Category for Media Gallery
+ *
+ * @category Toolkit
+ * @package Media
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @release Release: (0.1)
+ * @link <>
+ */
+class Toolkit_Photos_Models_Category
+{
+ private $_id;
+ private $_category;
+ private $_exclusive;
+ private $_slideshow;
+ private $_pos;
+
+ const TABLE_NAME = 'photos.photo_category';
+ const PRI_KEY = 'id';
+ const SORT = 'pos';
+
+ private function __construct($values)
+ {
+ extract($values);
+ $this->setCategory($category)
+ ->setExclusive($exclusive)
+ ->setSlideShow($slideshow)
+ ->setPos($pos);
+ if ($id) {
+ $this->setId($id);
+ }
+ }
+
+ static public function createByValues($values)
+ {
+ return new Toolkit_Photos_Models_Category($values);
+ }
+
+ public function getFirstPhoto()
+ {
+ $dbh = Toolkit_Database::getInstance();
+ try {
+ $sql = "
+ SELECT p.image
+ FROM photos.photo p, photos.photo2category p2c
+ WHERE p2c.pos = 1
+ AND p2c.photo = p.id
+ AND p2c.category = :catid";
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(':catid', $this->getId(), PDO::PARAM_INT);
+ $stmt->execute();
+ return $stmt->fetchColumn();
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ public function getTotalNumberOfPhotos()
+ {
+ $dbh = Toolkit_Database::getInstance();
+ try {
+ $sql = "
+ SELECT count(p.id)
+ FROM photos.photo p, photos.photo2category p2c
+ WHERE p2c.photo = p.id
+ AND p2c.category = :catid";
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(':catid', $this->getId(), PDO::PARAM_INT);
+ $stmt->execute();
+ return $stmt->fetchColumn();
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ public function getId()
+ {
+ return (int)$this->_id;
+ }
+
+ public function setId($id)
+ {
+ $this->_id
+ = (filter_var($id, FILTER_VALIDATE_INT))
+ ? $id
+ : null;
+ return $this;
+ }
+
+ public function getPos()
+ {
+ return (int)$this->_pos;
+ }
+
+ public function setPos($pos)
+ {
+ $this->_pos = (int)$pos;
+ return $this;
+ }
+
+
+ public function getCategory()
+ {
+ return $this->_category;
+ }
+
+ public function setCategory($category)
+ {
+ $this->_category = $category;
+ return $this;
+ }
+
+ public function getExclusive()
+ {
+ return (bool)$this->_exclusive;
+ }
+
+ public function setExclusive($exclusive)
+ {
+ $this->_exclusive = (bool)$exclusive;
+ return $this;
+ }
+
+ public function getSlideShow()
+ {
+ return (bool)$this->_slideshow;
+ }
+
+ public function setSlideShow($slideshow)
+ {
+ $this->_slideshow = (bool)$slideshow;
+ return $this;
+ }
+
+
+}
--- /dev/null
+<?php
+
+/**
+ * MediaMapper.php
+ *
+ * PHP version 5.3
+ *
+ * @category Toolkit
+ * @package Media
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: (0.1)
+ * @link <>
+ */
+
+/**
+ * Toolkit_Photos_Models_MediaMapper
+ *
+ * Maps the Media Objects to methods to create and generate list of
+ * categories and photos.
+ *
+ * @category Toolkit
+ * @package Media
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @release Release: (0.1)
+ * @link <>
+ */
+class Toolkit_Photos_Models_MediaMapper
+{
+ private $_dbh;
+
+ public function __construct(PDO $dbh)
+ {
+ $this->_dbh = $dbh;
+ }
+
+ public function fetchAllCategories()
+ {
+ $categories = new ArrayObject();
+ try {
+ $sql = "
+ SELECT *
+ FROM " . Toolkit_Photos_Models_Category::TABLE_NAME . "
+ ORDER BY " . Toolkit_Photos_Models_Category::SORT;
+ $stmt = $this->_dbh->query($sql);
+ while ($category = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $categories->append(
+ Toolkit_Photos_Models_Category::createByValues($category)
+ );
+ }
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ return $categories;
+ }
+
+ public function fetchAllPhotos($catId)
+ {
+ $photos = new ArrayObject();
+ try {
+ $sql = "
+ SELECT *
+ FROM " . Toolkit_Photos_Models_Photo::TABLE_NAME . "
+ WHERE catid = :catid
+ ORDER BY " . Toolkit_Photos_Models_Photo::SORT;
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':catid', $catId, PDO::PARAM_INT);
+ $stmt->execute();
+ while ($photo = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $photos->append(
+ Toolkit_Photos_Models_Photo::createByValues($photo)
+ );
+ }
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ return $photos;
+ }
+
+ public function fetchPhotosByName($distinct = false)
+ {
+ $nameSearch = filter_var($_REQUEST['photoName'], FILTER_SANITIZE_STRING);
+ if (!$nameSearch) {
+ return false;
+ }
+ $photos = new ArrayObject();
+ try {
+ $nameSearch = $this->_dbh->quote('%' . $nameSearch . '%');
+ $select
+ = (!$distinct)
+ ? '*'
+ : 'DISTINCT ON (title) title';
+ $orderBy
+ = (!$distinct)
+ ? Toolkit_Photos_Models_Photo::SORT
+ : 'title';
+ $sql = "
+ SELECT $select
+ FROM " . Toolkit_Photos_Models_Photo::TABLE_NAME . "
+ WHERE title ilike $nameSearch
+ ORDER BY $orderBy";
+ $stmt = $this->_dbh->query($sql);
+ while ($photo = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $photos->append(
+ Toolkit_Photos_Models_Photo::createByValues($photo)
+ );
+ }
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ return $photos;
+ }
+
+ public function fetchPhotosByNameAndCats(
+ $nameSearch,
+ $galleries,
+ $distinct = false
+ ) {
+ if (!$nameSearch) {
+ die('here');
+ return false;
+ }
+ $photos = new ArrayObject();
+ try {
+ $nameSearch = $this->_dbh->quote('%' . $nameSearch . '%');
+ $select
+ = (!$distinct)
+ ? '*'
+ : 'DISTINCT ON (title) title';
+ $where
+ = (!empty($galleries))
+ ? " AND id IN (SELECT photo FROM photo2category WHERE category IN ("
+ . implode(",", $galleries) . "))"
+ : '';
+ $orderBy
+ = (!$distinct)
+ ? Toolkit_Photos_Models_Photo::SORT
+ : 'title';
+ $sql = "
+ SELECT $select
+ FROM " . Toolkit_Photos_Models_Photo::TABLE_NAME . "
+ WHERE title ilike $nameSearch
+ $where
+ ORDER BY $orderBy";
+ $stmt = $this->_dbh->query($sql);
+ while ($photo = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $photos->append(
+ Toolkit_Photos_Models_Photo::createByValues($photo)
+ );
+ }
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ return $photos;
+ }
+
+ public function fetchAllPhotosByCatid($catId, $filter = null)
+ {
+ $photos = new ArrayObject();
+ try {
+ $where
+ = ($filter)
+ ? "AND " . implode(" AND ", $filter)
+ : '';
+ $sql = "
+ SELECT p.*
+ FROM " . Toolkit_Photos_Models_Photo::TABLE_NAME . " p,
+ " . Toolkit_Photos_Models_Photo2Category::TABLE_NAME . " p2c
+ WHERE p2c.category = :catid
+ AND p2c.photo = p.id
+ $where
+ ORDER BY p2c.pos";
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':catid', $catId, PDO::PARAM_INT);
+ $stmt->execute();
+ while ($photo = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $photos->append(
+ Toolkit_Photos_Models_Photo::createByValues($photo)
+ );
+ }
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ return $photos;
+ }
+
+ public function fetchPhoto2CategoryByPhotoId($photoId)
+ {
+ $photo2Categories = new ArrayObject();
+ try {
+ $sql = "
+ SELECT *
+ FROM " . Toolkit_Photos_Models_Photo2Category::TABLE_NAME . "
+ WHERE photo = :photo
+ ORDER BY " . Toolkit_Photos_Models_Photo2Category::SORT;
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':photo', $photoId, PDO::PARAM_INT);
+ $stmt->execute();
+ while ($photo = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $photo2Categories->offsetSet(
+ $photo['category'],
+ Toolkit_Photos_Models_Photo2Category::createByValues($photo)
+ );
+ }
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ return $photo2Categories;
+ }
+
+ public function fetchPhoto2Category($catId)
+ {
+ $photo2Categories = new ArrayObject();
+ try {
+ $sql = "
+ SELECT *
+ FROM " . Toolkit_Photos_Models_Photo2Category::TABLE_NAME . "
+ WHERE category = :catid
+ ORDER BY " . Toolkit_Photos_Models_Photo2Category::SORT;
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':catid', $catId, PDO::PARAM_INT);
+ $stmt->execute();
+ while ($photo = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $photo2Categories->append(
+ Toolkit_Photos_Models_Photo2Category::createByValues($photo)
+ );
+ }
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ return $photo2Categories;
+ }
+
+ public function fetchCategoryPages($catId)
+ {
+ $pages2Categories = new ArrayObject();
+ try {
+ $sql = "
+ SELECT pcb.buscat_id as page, p.navigation_name as page_name, pcb.pos as pos
+ FROM photo_category_bus pcb, photo_category pc, pages p
+ WHERE pc.id IN (
+ SELECT photocat_id
+ FROM photo_category_bus
+ WHERE photocat_id = :catid)
+ AND pcb.photocat_id = pc.id
+ AND p.id = pcb.buscat_id
+ ORDER BY pcb.pos";
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':catid', $catId, PDO::PARAM_INT);
+ $stmt->execute();
+ while ($photo = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $pages2Categories->append(
+ $photo
+ );
+ }
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ return $pages2Categories;
+ }
+
+ public function fixAllPhoto2Cats()
+ {
+ $sql = "
+ DELETE FROM photos.photo2category";
+ $this->_dbh->query($sql);
+ // first grab all categories
+ $categories = $this->fetchAllCategories();
+ foreach ($categories as $category) {
+ var_dump($category);
+ $photos = $this->fetchAllPhotos($category->getId());
+ var_dump($photos);
+ if ($photos) {
+ foreach ($photos as $photo) {
+ $photo2Category
+ = Toolkit_Photos_Models_Photo2Category::createByValues(
+ array(
+ 'category' => $category->getId(),
+ 'photo' => $photo->getId(),
+ 'pos' => $photo->getPos()
+ )
+ );
+ $this->savePhoto2Category($photo2Category);
+ }
+ }
+ }
+ exit;
+ }
+
+ public function fetchPhotoById($photoId)
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM " . Toolkit_Photos_Models_Photo::TABLE_NAME . "
+ WHERE " . Toolkit_Photos_Models_Photo::PRI_KEY . " = :id";
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':id', $photoId, PDO::PARAM_INT);
+ $stmt->execute();
+ return Toolkit_Photos_Models_Photo::createByValues(
+ $stmt->fetch(PDO::FETCH_ASSOC)
+ );
+
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+
+ }
+
+ public function saveCategoryWithPost()
+ {
+ if ($_REQUEST['Cancel']) {
+ return true;
+ }
+ if ($_REQUEST['Delete']) {
+ // delete the category
+ $category = $this->fetchCategoryById($_REQUEST['id']);
+ $this->removeCategory($category);
+ return true;
+ }
+ $postedData = filter_var_array(
+ $_POST,
+ array(
+ 'id' => FILTER_VALIDATE_INT,
+ 'pos' => FILTER_VALIDATE_INT,
+ 'pages' => array(
+ 'filter' => FILTER_VALIDATE_INT,
+ 'flags' => FILTER_FORCE_ARRAY
+ ),
+ 'category' => array(
+ 'filter' => FILTER_SANITIZE_STRIPPED,
+ 'flags' => FILTER_FLAG_NO_ENCODE_QUOTES
+ ),
+ 'exclusive' => FILTER_VALIDATE_BOOLEAN,
+ 'slideshow' => FILTER_VALIDATE_BOOLEAN
+ )
+ );
+ if (get_magic_quotes_gpc()) {
+ $postedData['category'] = stripslashes($postedData['category']);
+ }
+
+ $category = Toolkit_Photos_Models_Category::createByValues(
+ $postedData
+ );
+ //var_dump($category);exit;
+ $id = $this->saveCategory($category);
+
+ try {
+ $this->_dbh->beginTransaction();
+ if ($postedData['id']) {
+ $sql = "
+ DELETE
+ FROM " . Toolkit_Photos_Models_Page2Category::TABLE_NAME . "
+ WHERE photocat_id = :category";
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':category', $postedData['id'], PDO::PARAM_INT);
+ $stmt->execute();
+ }
+ if ( is_array($postedData['pages'])
+ && !empty($postedData['pages'])
+ ) {
+ foreach ($postedData['pages'] as $pageId) {
+ $page2Category
+ = Toolkit_Photos_Models_Page2Category::createByValues(
+ array(
+ 'buscat_id' => $pageId,
+ 'photocat_id' => $category->getId()
+ )
+ );
+ $this->savePage2Category($page2Category);
+ }
+ }
+
+ $this->_dbh->commit();
+ } catch (PDOException $e) {
+ $this->_dbh->rollBack();
+ Toolkit_Common::handleError($e);
+ }
+
+ return true;
+ }
+
+ public function saveCategory(
+ Toolkit_Photos_Models_Category $category
+ ) {
+ if ($category->getId()) {
+ $sql = "
+ UPDATE " . Toolkit_Photos_Models_Category::TABLE_NAME . "
+ SET category = :category,
+ exclusive = :exclusive,
+ slideshow = :slideshow,
+ pos = :pos
+ WHERE " . Toolkit_Photos_Models_Category::PRI_KEY . " = :id";
+
+ } else {
+ $sql = "
+ INSERT INTO " . Toolkit_Photos_Models_Category::TABLE_NAME . "
+ (category, exclusive, slideshow, pos)
+ VALUES
+ (:category, :exclusive, :slideshow, :pos)
+ RETURNING " . Toolkit_Photos_Models_Category::PRI_KEY;
+ }
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':category', $category->getCategory());
+ $stmt->bindParam(':pos', $category->getPos(), PDO::PARAM_INT);
+ $stmt->bindParam(':exclusive', $category->getExclusive(), PDO::PARAM_BOOL);
+ $stmt->bindParam(':slideshow', $category->getSlideShow(), PDO::PARAM_BOOL);
+ if ($category->getId()) {
+ $stmt->bindParam(':id', $category->getId(), PDO::PARAM_INT);
+ }
+ $stmt->execute();
+ if (!$category->getId()) {
+ $category->setId($stmt->fetchColumn());
+ }
+ return $category->getId();
+ }
+
+ public function savePage2Category(
+ Toolkit_Photos_Models_Page2Category $page2Category
+ ) {
+ if ($page2Category->getId()) {
+ $sql = "
+ UPDATE " . Toolkit_Photos_Models_Page2Category::TABLE_NAME . "
+ SET photocat_id = :category,
+ buscat_id = :page
+ WHERE " . Toolkit_Photos_Models_Page2Category::PRI_KEY . " = :id";
+
+ } else {
+ $sql = "
+ INSERT INTO " . Toolkit_Photos_Models_Page2Category::TABLE_NAME . "
+ (photocat_id, buscat_id)
+ VALUES
+ (:category, :page)
+ RETURNING " . Toolkit_Photos_Models_Page2Category::PRI_KEY;
+ }
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':page', $page2Category->getBuscatId(), PDO::PARAM_INT);
+ $stmt->bindParam(':category', $page2Category->getPhotocatId(), PDO::PARAM_INT);
+ if ($page2Category->getId()) {
+ $stmt->bindParam(':id', $page2Category->getId(), PDO::PARAM_INT);
+ }
+ $stmt->execute();
+ return ($page2Category->getId())
+ ? $page2Category->getId()
+ : $stmt->fetchColumn();
+ }
+
+ public function savePhoto2Category(
+ Toolkit_Photos_Models_Photo2Category $photo2Category
+ ) {
+ if ($photo2Category->getId()) {
+ $sql = "
+ UPDATE " . Toolkit_Photos_Models_Photo2Category::TABLE_NAME . "
+ SET photo = :photo,
+ category = :category,
+ pos = :pos
+ WHERE " . Toolkit_Photos_Models_Photo2Category::PRI_KEY . " = :id";
+
+ } else {
+ $sql = "
+ INSERT INTO " . Toolkit_Photos_Models_Photo2Category::TABLE_NAME . "
+ (photo, category, pos)
+ VALUES
+ (:photo, :category, :pos)
+ RETURNING " . Toolkit_Photos_Models_Photo2Category::PRI_KEY;
+ }
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':photo', $photo2Category->getPhoto(), PDO::PARAM_INT);
+ $stmt->bindParam(':category', $photo2Category->getCategory(), PDO::PARAM_INT);
+ $stmt->bindParam(':pos', $photo2Category->getPos(), PDO::PARAM_INT);
+ if ($photo2Category->getId()) {
+ $stmt->bindParam(':id', $photo2Category->getId(), PDO::PARAM_INT);
+ }
+ $stmt->execute();
+ return ($photo2Category->getId())
+ ? $photo2Category->getId()
+ : $stmt->fetchColumn();
+ }
+
+ public function fetchCategoryById($categoryId)
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM " . Toolkit_Photos_Models_Category::TABLE_NAME . "
+ WHERE " . Toolkit_Photos_Models_Category::PRI_KEY . " = :id";
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':id', $categoryId, PDO::PARAM_INT);
+ $stmt->execute();
+ return Toolkit_Photos_Models_Category::createByValues(
+ $stmt->fetch(PDO::FETCH_ASSOC)
+ );
+
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+
+ }
+
+ public function savePhotoPositionsByCategory($photos, $categoryId)
+ {
+ if (!is_array($photos) || empty($photos)) {
+ return false;
+ }
+ var_dump($photos);
+ var_dump($categoryId);
+ try {
+ $this->_dbh->beginTransaction();
+ $sql = "
+ DELETE
+ FROM " . Toolkit_Photos_Models_Photo2Category::TABLE_NAME . "
+ WHERE category = :category";
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':category', $categoryId, PDO::PARAM_INT);
+ $stmt->execute();
+
+ foreach ($photos as $position => $photoId) {
+ $photo2Category
+ = Toolkit_Photos_Models_Photo2Category::createByValues(
+ array(
+ 'photo' => $photoId,
+ 'category' => $categoryId,
+ 'pos' => $position + 1
+ )
+ );
+ $this->savePhoto2Category($photo2Category);
+ var_dump($photo2Category);
+ }
+
+ $this->_dbh->commit();
+ } catch (PDOException $e) {
+ $this->_dbh->rollBack();
+ Toolkit_Common::handleError($e);
+ }
+
+ }
+
+ public function saveCategoryPositionsByArray($cats)
+ {
+ if (!is_array($cats) || empty($cats)) {
+ return false;
+ }
+// var_dump($cats);exit;
+ foreach ($cats as $position => $catId) {
+ $category = $this->fetchCategoryById($catId);
+ $category->setPos((int)$position + 1);
+ $this->saveCategory($category);
+ }
+ }
+
+ public function savePhotoWithPost()
+ {
+ if ($_REQUEST['Cancel']) {
+ return true;
+ }
+ if ($_REQUEST['Delete']) {
+ // delete the photo
+ $photo = $this->fetchPhotoById($_REQUEST['id']);
+ $this->removePhoto($photo);
+ return true;
+ }
+
+ if ( $_FILES['image']['name']
+ && !$_FILES['image']['error']
+ ) {
+ $fs = new Toolkit_FileServer_ImageAdapter();
+ $image = $fs->upload('image');
+ }
+ $postedData = filter_var_array(
+ $_POST,
+ array(
+ 'id' => FILTER_VALIDATE_INT,
+ 'catid' => FILTER_VALIDATE_INT,
+ 'title' => array(
+ 'filter' => FILTER_SANITIZE_STRING,
+ 'flags' => FILTER_FLAG_NO_ENCODE_QUOTES
+ ),
+ 'image' => array(
+ 'filter' => FILTER_SANITIZE_STRING,
+ 'flags' => FILTER_FLAG_NO_ENCODE_QUOTES
+ ),
+ 'description' => array(
+ 'filter' => FILTER_SANITIZE_STRING,
+ 'flags' => FILTER_FLAG_NO_ENCODE_QUOTES
+ ),
+ 'photo2Categories' => array(
+ 'filter' => FILTER_VALIDATE_INT,
+ 'flags' => FILTER_FORCE_ARRAY
+ ),
+ 'pos' => FILTER_VALIDATE_INT,
+ 'del_img' => FILTER_VALIDATE_BOOLEAN,
+ 'download' => FILTER_VALIDATE_BOOLEAN,
+ 'exclusive' => FILTER_VALIDATE_BOOLEAN,
+ )
+ );
+
+ if (!$image && $postedData['del_img']) {
+ $postedData['image'] = '';
+ } else if ($image) {
+ $postedData['image'] = $image['name'];
+ }
+ $photo = Toolkit_Photos_Models_Photo::createByValues(
+ $postedData
+ );
+ $photoId = $this->savePhoto($photo);
+ $postedData['id'] = $photoId;
+ $this->savePhoto2CategoryData($postedData);
+ return $photoId;
+ }
+
+ public function savePhoto2CategoryData($data)
+ {
+ if (!is_array($data) || empty($data)) {
+ return false;
+ }
+// var_dump($data);
+ // need to get the current photo2category records for this photo
+ $currentCategories = $this->fetchPhoto2CategoryByPhotoId($data['id']);
+// var_dump($currentCategories);
+ foreach ($data['photo2Categories'] as $catId) {
+ // if the offest does not exists then the photo need to be
+ // added to the category
+ if (!$currentCategories->offsetExists($catId)) {
+ $photoCatsNew = $this->fetchPhoto2Category($catId);
+ $newPosition = $photoCatsNew->count() + 1;
+ // need to add photo to the photo2category record as last pos
+ $newPhoto2Cat
+ = Toolkit_Photos_Models_Photo2Category::createByValues(
+ array(
+ 'photo' => $data['id'],
+ 'category' => $catId,
+ 'pos' => $newPosition
+ )
+ );
+// var_dump($newPhoto2Cat);
+ $this->savePhoto2Category($newPhoto2Cat);
+// var_dump('adding record for category ' . $catId);
+ }
+ // for each step through remove the iteration in the ArrayObject
+ // that way we know if we have to remove any records and reorder
+ $currentCategories->offsetUnset($catId);
+ }
+ foreach ($currentCategories as $photo2Category) {
+// var_dump($photo2Category);
+ $this->removePhoto2Category($photo2Category);
+ }
+ }
+
+ public function removeCategory(
+ Toolkit_Photos_Models_Category $category
+ ) {
+ // if there's any photos in the category that are only in that
+ // category then it will need to delete them.
+ try {
+ // 1. delete this category
+ $sql = "
+ DELETE
+ FROM photos.photo_category
+ WHERE id = :id";
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':id', $category->getId(), PDO::PARAM_INT);
+ $stmt->execute();
+ // 2. delete all references in photo2category table for this category
+ $sql = "
+ DELETE
+ FROM photos.photo2category
+ WHERE category = :id";
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':id', $category->getId(), PDO::PARAM_INT);
+ $stmt->execute();
+ // 3. remove photos if they are orphaned from this delete
+ $sql = "
+ DELETE
+ FROM photos.photo
+ WHERE id NOT IN (
+ SELECT distinct photo
+ FROM photos.photo2category
+ )";
+ $this->_dbh->query($sql);
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+
+ }
+
+ public function removePhoto(
+ Toolkit_Photos_Models_Photo $photo
+ ) {
+ $photo2Categories = $this->fetchPhoto2CategoryByPhotoId(
+ $photo->getId()
+ );
+
+ foreach ($photo2Categories as $photoCat) {
+ $this->removePhoto2Category($photoCat);
+ }
+ try {
+ $sql = "
+ DELETE
+ FROM photos.photo
+ WHERE id = :id";
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':id', $photo->getId(), PDO::PARAM_INT);
+ $stmt->execute();
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+
+ }
+
+ public function removePhoto2Category(
+ Toolkit_Photos_Models_Photo2Category $photo2Category
+ ) {
+ try {
+ $sql = "
+ DELETE
+ FROM " . Toolkit_Photos_Models_Photo2Category::TABLE_NAME . "
+ WHERE id = :id";
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':id', $photo2Category->getId(), PDO::PARAM_INT);
+ $stmt->execute();
+ $sql = "
+ UPDATE " . Toolkit_Photos_Models_Photo2Category::TABLE_NAME . "
+ SET pos = pos - 1
+ WHERE pos >= :pos
+ AND category = :category";
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':pos', $photo2Category->getPos(), PDO::PARAM_INT);
+ $stmt->bindParam(':category', $photo2Category->getCategory(), PDO::PARAM_INT);
+ $stmt->execute();
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+
+ }
+
+ public function savePhoto(
+ Toolkit_Photos_Models_Photo $photo
+ ) {
+ try {
+ if ($photo->getId()) {
+ $sql = "
+ UPDATE " . Toolkit_Photos_Models_Photo::TABLE_NAME . "
+ SET title = :title,
+ catid = :catid,
+ description = :description,
+ image = :image,
+ pos = :pos,
+ download = :download,
+ exclusive = :exclusive
+ WHERE " . Toolkit_Photos_Models_Photo::PRI_KEY . " = :id";
+
+ } else {
+ $sql = "
+ INSERT INTO " . Toolkit_Photos_Models_Photo::TABLE_NAME . "
+ (title, catid, description, image, pos, download, exclusive)
+ VALUES
+ (:title, :catid, :description, :image, :pos, :download, :exclusive)
+ RETURNING " . Toolkit_Photos_Models_Photo::PRI_KEY;
+ }
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':title', $photo->getTitle());
+ $stmt->bindParam(':catid', $photo->getCatid(), PDO::PARAM_INT);
+ $stmt->bindParam(':description', $photo->getDescription());
+ $stmt->bindParam(':image', $photo->getImage());
+ $stmt->bindParam(':pos', $photo->getPos(), PDO::PARAM_INT);
+ $stmt->bindParam(':download', $photo->getDownload(), PDO::PARAM_BOOL);
+ $stmt->bindParam(':exclusive', $photo->getExclusive(), PDO::PARAM_BOOL);
+ if ($photo->getId()) {
+ $stmt->bindParam(':id', $photo->getId(), PDO::PARAM_INT);
+ }
+ $stmt->execute();
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+
+ return ($photo->getId())
+ ? $photo->getId()
+ : $stmt->fetchColumn();
+ }
+
+ public function saveUserWithPost()
+ {
+ $postedData = filter_var_array(
+ $_POST,
+ array(
+ 'id' => FILTER_VALIDATE_INT,
+ 'status' => FILTER_SANITIZE_STRING,
+ 'expire' => array(
+ 'filter' => FILTER_VALIDATE_REGEXP,
+ 'options' => array(
+ 'regexp' => '%[0-9]{2}/[0-9]{2}/[0-9]{4}%'
+ )
+ ),
+ 'phone' => FILTER_SANITIZE_STRING,
+ 'email' => array(
+ 'filter' => FILTER_SANITIZE_STRING,
+ 'flags' => FILTER_FLAG_NO_ENCODE_QUOTES
+ ),
+ 'media_pass' => array(
+ 'filter' => FILTER_SANITIZE_STRING,
+ 'flags' => FILTER_FLAG_NO_ENCODE_QUOTES
+ ),
+ 'company' => array(
+ 'filter' => FILTER_SANITIZE_STRING,
+ 'flags' => FILTER_FLAG_NO_ENCODE_QUOTES
+ ),
+ 'title' => array(
+ 'filter' => FILTER_SANITIZE_STRING,
+ 'flags' => FILTER_FLAG_NO_ENCODE_QUOTES
+ ),
+ 'fname' => array(
+ 'filter' => FILTER_SANITIZE_STRING,
+ 'flags' => FILTER_FLAG_NO_ENCODE_QUOTES
+ ),
+ 'lname' => array(
+ 'filter' => FILTER_SANITIZE_STRING,
+ 'flags' => FILTER_FLAG_NO_ENCODE_QUOTES
+ ),
+ 'address' => array(
+ 'filter' => FILTER_SANITIZE_STRING,
+ 'flags' => FILTER_FLAG_NO_ENCODE_QUOTES
+ ),
+ 'address2' => array(
+ 'filter' => FILTER_SANITIZE_STRING,
+ 'flags' => FILTER_FLAG_NO_ENCODE_QUOTES
+ ),
+ 'city' => array(
+ 'filter' => FILTER_SANITIZE_STRING,
+ 'flags' => FILTER_FLAG_NO_ENCODE_QUOTES
+ ),
+ 'state' => array(
+ 'filter' => FILTER_SANITIZE_STRING,
+ 'flags' => FILTER_FLAG_NO_ENCODE_QUOTES
+ ),
+ 'zip' => array(
+ 'filter' => FILTER_SANITIZE_STRING,
+ 'flags' => FILTER_FLAG_NO_ENCODE_QUOTES
+ )
+ )
+ );
+ if ($postedData['status'] == 'approved') {
+ $postedData['approved'] = true;
+ $postedData['denied'] = false;
+ } else {
+ $postedData['approved'] = false;
+ $postedData['denied'] = true;
+ }
+ if (!$postedData['expire']) {
+ $postedData['expire'] = null;
+ }
+
+ $user = Toolkit_Photos_Models_User::createByValues(
+ $postedData
+ );
+ return $this->saveUser($user);
+ }
+
+ public function saveUser(
+ Toolkit_Photos_Models_User $user
+ ) {
+ if ($user->getId()) {
+ $sql = "
+ UPDATE " . Toolkit_Photos_Models_User::TABLE_NAME . "
+ SET company = :company,
+ title = :title,
+ fname = :fname,
+ lname = :lname,
+ email = :email,
+ phone = :phone,
+ address = :address,
+ address2 = :address2,
+ city = :city,
+ state = :state,
+ zip = :zip,
+ media = true,
+ approved = :approved,
+ denied = :denied,
+ expire = :expire
+ WHERE " . Toolkit_Photos_Models_User::PRI_KEY . " = :id";
+
+ } else {
+ $sql = "
+ INSERT INTO " . Toolkit_Photos_Models_User::TABLE_NAME . "
+ (fname, lname, email, phone,
+ address, address2, city, state, zip,
+ approved, denied, expire, media)
+ VALUES
+ (:fname, :lname, :email, :phone,
+ :address, :address2, :city, :state, :zip,
+ :approved, :denied, :expire, true)
+ RETURNING " . Toolkit_Photos_Models_User::PRI_KEY;
+ }
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':expire', $user->getExpire());
+ $stmt->bindParam(':company', $user->getCompany());
+ $stmt->bindParam(':title', $user->getTitle());
+ $stmt->bindParam(':fname', $user->getFname());
+ $stmt->bindParam(':lname', $user->getLname());
+ $stmt->bindParam(':email', $user->getEmail());
+ $stmt->bindParam(':phone', $user->getPhone());
+ $stmt->bindParam(':address', $user->getAddress());
+ $stmt->bindParam(':address2', $user->getAddress2());
+ $stmt->bindParam(':city', $user->getCity());
+ $stmt->bindParam(':state', $user->getState());
+ $stmt->bindParam(':zip', $user->getZip());
+ $stmt->bindParam(':approved', $user->getApproved(), PDO::PARAM_BOOL);
+ $stmt->bindParam(':denied', $user->getDenied(), PDO::PARAM_BOOL);
+ if ($user->getId()) {
+ $stmt->bindParam(':id', $user->getId(), PDO::PARAM_INT);
+ }
+ $stmt->execute();
+ return ($user->getId())
+ ? $user->getId()
+ : $stmt->fetchColumn();
+ }
+
+ public function fetchUserById($userId)
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM " . Toolkit_Photos_Models_User::TABLE_NAME . "
+ WHERE " . Toolkit_Photos_Models_User::PRI_KEY . " = :id
+ AND " . Toolkit_Photos_Models_User::WHERE;
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':id', $userId, PDO::PARAM_INT);
+ $stmt->execute();
+ return Toolkit_Photos_Models_User::createByValues(
+ $stmt->fetch(PDO::FETCH_ASSOC)
+ );
+
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+
+ }
+
+ public function fetchUserByEmail($email)
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM " . Toolkit_Photos_Models_User::TABLE_NAME . "
+ WHERE " . Toolkit_Photos_Models_User::EMAIL . " = :email
+ AND " . Toolkit_Photos_Models_User::WHERE;
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->bindParam(':email', $email, PDO::PARAM_INT);
+ $stmt->execute();
+ return Toolkit_Photos_Models_User::createByValues(
+ $stmt->fetch(PDO::FETCH_ASSOC)
+ );
+
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+
+ }
+
+ public function fetchAllUsers()
+ {
+ $users = new ArrayObject();
+ try {
+ $sql = "
+ SELECT *
+ FROM " . Toolkit_Media_Models_User::TABLE_NAME . "
+ WHERE media = true
+ ORDER BY " . Toolkit_Media_Models_User::SORT;
+ $sql .= " LIMIT 10 OFFSET 0";
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->execute();
+ while ($photo = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $users->append(
+ Toolkit_Media_Models_User::createByValues($photo)
+ );
+ }
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ return $users;
+ }
+
+ public function fetchUsers(array $filters = null)
+ {
+ $users = new ArrayObject();
+ try{
+ $where = (is_array($filters) && !empty($filters))
+ ? "AND " . implode(" AND ", $filters)
+ : '';
+ $sql = "
+ SELECT *
+ FROM " . Toolkit_Photos_Models_User::TABLE_NAME . "
+ WHERE media = true
+ $where
+ ORDER BY " . Toolkit_Photos_Models_User::SORT;
+ $sql .= " LIMIT 10 OFFSET 0";
+ $stmt = $this->_dbh->prepare($sql);
+ $stmt->execute();
+ while ($photo = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $users->append(
+ Toolkit_Photos_Models_User::createByValues($photo)
+ );
+ }
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ return $users;
+ }
+
+}
--- /dev/null
+<?php
+
+/**
+ * Photo2Category.php
+ *
+ * PHP version 5.3
+ *
+ * @category Toolkit
+ * @package Photos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: (0.1)
+ * @link <>
+ */
+
+/**
+ * Toolkit_Package_Photo2Category
+ *
+ * Description of Photo2Category
+ *
+ * @category Toolkit
+ * @package Photos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @release Release: (0.1)
+ * @link <>
+ */
+class Toolkit_Photos_Models_Page2Category
+{
+ private $_id;
+ private $_photocatId;
+ private $_buscatId;
+
+ const TABLE_NAME = 'photos.photo_category_bus';
+ const PRI_KEY = 'id';
+ const SORT = 'pos';
+
+ private function __construct($values)
+ {
+ extract($values);
+ $this->setBuscatId($buscat_id)
+ ->setPhotocatId($photocat_id);
+ if ($id) {
+ $this->setId($id);
+ }
+ }
+
+ static public function createByValues($values)
+ {
+ return new Toolkit_Photos_Models_Page2Category($values);
+ }
+
+ public function getId()
+ {
+ return (int)$this->_id;
+ }
+
+ public function setId($id)
+ {
+ $this->_id
+ = (filter_var($id, FILTER_VALIDATE_INT))
+ ? $id
+ : null;
+ return $this;
+ }
+
+ public function getPhotocatId()
+ {
+ return $this->_photocatId;
+ }
+
+ public function setPhotocatId($photocatId)
+ {
+ $this->_photocatId = $photocatId;
+ return $this;
+ }
+
+ public function getBuscatId()
+ {
+ return $this->_buscatId;
+ }
+
+ public function setBuscatId($buscatId)
+ {
+ $this->_buscatId = $buscatId;
+ return $this;
+ }
+
+
+}
--- /dev/null
+<?php
+
+/**
+ * Photo.php
+ *
+ * PHP version 5.3
+ *
+ * @category Toolkit
+ * @package Media
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: (0.1)
+ * @link <>
+ */
+
+/**
+ * Toolkit_Photos_Models_Photo
+ *
+ * Represents the Photo for Media Gallery
+ *
+ * @category Toolkit
+ * @package Media
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @release Release: (0.1)
+ * @link <>
+ */
+class Toolkit_Photos_Models_Photo
+{
+ private $_id;
+ private $_title;
+ private $_description;
+ private $_image;
+ private $_catid;
+ private $_pos;
+ private $_download;
+ private $_exclusive;
+
+ const TABLE_NAME = 'photos.photo';
+ const PRI_KEY = 'id';
+ const SORT = 'pos';
+
+ private function __construct($values)
+ {
+ extract($values);
+ $this->setTitle($title)
+ ->setDescription($description)
+ ->setImage($image)
+ ->setCatid($catid)
+ ->setPos($pos)
+ ->setDownload($download)
+ ->setExclusive($exclusive);
+ if ($id) {
+ $this->setId($id);
+ }
+ }
+
+ static public function createByValues($values)
+ {
+ return new Toolkit_Photos_Models_Photo($values);
+ }
+
+ public function getId()
+ {
+ return (int)$this->_id;
+ }
+
+ public function setId($id)
+ {
+ $this->_id
+ = (filter_var($id, FILTER_VALIDATE_INT))
+ ? $id
+ : null;
+ return $this;
+ }
+
+ public function getTitle()
+ {
+ return $this->_title;
+ }
+
+ public function setTitle($title)
+ {
+ $this->_title = $title;
+ return $this;
+ }
+
+ public function getDescription()
+ {
+ return $this->_description;
+ }
+
+ public function setDescription($description)
+ {
+ $this->_description = $description;
+ return $this;
+ }
+
+ public function getImage()
+ {
+ return $this->_image;
+ }
+
+ public function setImage($image)
+ {
+ $this->_image = $image;
+ return $this;
+ }
+
+ public function getCatid()
+ {
+ return (int)$this->_catid;
+ }
+
+ public function setCatid($catid)
+ {
+ $this->_catid = (int)$catid;
+ return $this;
+ }
+
+ public function getPos()
+ {
+ return (int)$this->_pos;
+ }
+
+ public function setPos($pos)
+ {
+ $this->_pos = (int)$pos;
+ return $this;
+ }
+
+ public function getDownload()
+ {
+ return (bool)$this->_download;
+ }
+
+ public function setDownload($download)
+ {
+ $this->_download = (bool)$download;
+ return $this;
+ }
+
+ public function getExclusive()
+ {
+ return (bool)$this->_exclusive;
+ }
+
+ public function setExclusive($exclusive)
+ {
+ $this->_exclusive = (bool)$exclusive;
+ return $this;
+ }
+
+
+}
--- /dev/null
+<?php
+
+/**
+ * Photo2Category.php
+ *
+ * PHP version 5.3
+ *
+ * @category Toolkit
+ * @package Photos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: (0.1)
+ * @link <>
+ */
+
+/**
+ * Toolkit_Package_Photo2Category
+ *
+ * Description of Photo2Category
+ *
+ * @category Toolkit
+ * @package Photos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @release Release: (0.1)
+ * @link <>
+ */
+class Toolkit_Photos_Models_Photo2Category
+{
+ private $_id;
+ private $_photo;
+ private $_category;
+ private $_pos;
+
+ const TABLE_NAME = 'photos.photo2category';
+ const PRI_KEY = 'id';
+ const SORT = 'pos';
+
+ private function __construct($values)
+ {
+ extract($values);
+ $this->setCategory($category)
+ ->setPhoto($photo)
+ ->setPos($pos);
+ if ($id) {
+ $this->setId($id);
+ }
+ }
+
+ static public function createByValues($values)
+ {
+ return new Toolkit_Photos_Models_Photo2Category($values);
+ }
+
+ public function getId()
+ {
+ return (int)$this->_id;
+ }
+
+ public function setId($id)
+ {
+ $this->_id
+ = (filter_var($id, FILTER_VALIDATE_INT))
+ ? $id
+ : null;
+ return $this;
+ }
+
+ public function getPhoto()
+ {
+ return (int)$this->_photo;
+ }
+
+ public function setPhoto($photo)
+ {
+ $this->_photo = (int)$photo;
+ return $this;
+ }
+
+ public function getCategory()
+ {
+ return (int)$this->_category;
+ }
+
+ public function setCategory($category)
+ {
+ $this->_category = (int)$category;
+ return $this;
+ }
+
+ public function getPos()
+ {
+ return (int)$this->_pos;
+ }
+
+ public function setPos($pos)
+ {
+ $this->_pos = (int)$pos;
+ return $this;
+ }
+
+
+}
--- /dev/null
+<?php
+
+/**
+ * User.php
+ *
+ * PHP version 5.3
+ *
+ * @category Toolkit
+ * @package Media
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: (0.1)
+ * @link <>
+ */
+
+/**
+ * Toolkit_Photos_Model_User
+ *
+ * Class representation of the User
+ *
+ * @category Toolkit
+ * @package Media
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @release Release: (0.1)
+ * @link <>
+ */
+class Toolkit_Photos_Models_User
+{
+ private $_id;
+ private $_company;
+ private $_title;
+ private $_fname;
+ private $_lname;
+ private $_email;
+ private $_address;
+ private $_address2;
+ private $_city;
+ private $_state;
+ private $_zip;
+ private $_phone;
+ private $_media;
+ private $_expire;
+ private $_mediaPass;
+ private $_approved;
+ private $_denied;
+
+ const TABLE_NAME = 'contacts.contact';
+ const PRI_KEY = 'id';
+ const SORT = 'lname,fname';
+ const EMAIL = 'email';
+ const WHERE = 'media = true';
+
+ private function __construct($values)
+ {
+ extract($values);
+ $this->setCompany($company)
+ ->setTitle($title)
+ ->setAddress($address)
+ ->setAddress2($address2)
+ ->setApproved($approved)
+ ->setMediaPass($media_pass)
+ ->setCity($city)
+ ->setDenied($denied)
+ ->setEmail($email)
+ ->setExpire($expire)
+ ->setFname($fname)
+ ->setLname($lname)
+ ->setMedia($media)
+ ->setPhone($phone)
+ ->setState($state)
+ ->setZip($zip);
+ if ($id) {
+ $this->setId($id);
+ }
+ }
+
+ public function createByValues($values)
+ {
+ if (is_array($values) && !empty($values)) {
+ return new Toolkit_Photos_Models_User($values);
+ } else {
+ return false;
+ }
+ }
+
+ public function getMediaPass()
+ {
+ return $this->_mediaPass;
+ }
+
+ public function setMediaPass($mediaPass)
+ {
+ $this->_mediaPass = $mediaPass;
+ return $this;
+ }
+
+
+ public function getId()
+ {
+ return (int)$this->_id;
+ }
+
+ public function setId($id)
+ {
+ $this->_id = (int)$id;
+ return $this;
+ }
+
+ public function getCompany()
+ {
+ return $this->_company;
+ }
+
+ public function setCompany($company)
+ {
+ $this->_company = $company;
+ return $this;
+ }
+
+ public function getTitle()
+ {
+ return $this->_title;
+ }
+
+ public function setTitle($title)
+ {
+ $this->_title = $title;
+ return $this;
+ }
+
+
+ public function getFname()
+ {
+ return $this->_fname;
+ }
+
+ public function setFname($fname)
+ {
+ $this->_fname = $fname;
+ return $this;
+ }
+
+ public function getLname()
+ {
+ return $this->_lname;
+ }
+
+ public function setLname($lname)
+ {
+ $this->_lname = $lname;
+ return $this;
+ }
+
+ public function getEmail()
+ {
+ return $this->_email;
+ }
+
+ public function setEmail($email)
+ {
+ $this->_email = $email;
+ return $this;
+ }
+
+ public function getAddress()
+ {
+ return $this->_address;
+ }
+
+ public function setAddress($address)
+ {
+ $this->_address = $address;
+ return $this;
+ }
+
+ public function getAddress2()
+ {
+ return $this->_address2;
+ }
+
+ public function setAddress2($address2)
+ {
+ $this->_address2 = $address2;
+ return $this;
+ }
+
+ public function getCity()
+ {
+ return $this->_city;
+ }
+
+ public function setCity($city)
+ {
+ $this->_city = $city;
+ return $this;
+ }
+
+ public function getState()
+ {
+ return $this->_state;
+ }
+
+ public function setState($state)
+ {
+ $this->_state = $state;
+ return $this;
+ }
+
+ public function getZip()
+ {
+ return $this->_zip;
+ }
+
+ public function setZip($zip)
+ {
+ $this->_zip = $zip;
+ return $this;
+ }
+
+ public function getPhone()
+ {
+ return $this->_phone;
+ }
+
+ public function setPhone($phone)
+ {
+ $this->_phone = $phone;
+ return $this;
+ }
+
+ public function getMedia()
+ {
+ return $this->_media;
+ }
+
+ public function setMedia($media)
+ {
+ $this->_media = (bool)$media;
+ return $this;
+ }
+
+ public function getExpire()
+ {
+ return $this->_expire;
+ }
+
+ public function setExpire($expire)
+ {
+ $this->_expire = $expire;
+ return $this;
+ }
+
+ public function getApproved()
+ {
+ return (bool)$this->_approved;
+ }
+
+ public function setApproved($approved)
+ {
+ $this->_approved = (bool)$approved;
+ return $this;
+ }
+
+ public function getDenied()
+ {
+ return (bool)$this->_denied;
+ }
+
+ public function setDenied($denied)
+ {
+ $this->_denied = (bool)$denied;
+ return $this;
+ }
+
+
+}
--- /dev/null
+<?php
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/**
+ * Description of Photo
+ *
+ * @author steve
+ */
+class Toolkit_Photos_Photo
+ extends Toolkit_Table
+{
+ public $tableName = 'photo';
+ protected $id;
+ protected $title;
+ protected $description;
+ protected $image;
+ protected $catid;
+ protected $pos;
+}
+
--- /dev/null
+<?php
+
+/**
+ * SlideShowCategoryFilter.php
+ *
+ * PHP version 5.3
+ *
+ * @category Toolkit
+ * @package Photos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: (0.1)
+ * @link <>
+ */
+
+/**
+ * Toolkit_Photos_SlideShowCategoryFilter
+ *
+ * Description of SlideShowFilter
+ *
+ * @category Toolkit
+ * @package Photos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2013 Gaslight Media
+ * @license Gaslight Media
+ * @release Release: (0.1)
+ * @link <>
+ */
+class Toolkit_Photos_SlideShowCategoryFilter
+ extends FilterIterator
+{
+ public function __construct(Iterator $iterator)
+ {
+ parent::__construct($iterator);
+ }
+
+ public function accept()
+ {
+ $category = $this->getInnerIterator()->current();
+ if ($category['slideshow']) {
+ return true;
+ }
+ return false;
+ }
+}
--- /dev/null
+; Production server configuration data
+[production]
+; Application settings
+application.name = "Image Library"
+application.path = BASE "Toolkit/Photos/Controllers"
+application.application = "Photos/Controllers"
+
+; turn on media exclusive flag for categories and photos
+; This option also may need other new fields not added yet to the contact table
+settings.mediaExclusive = Off
+settings.photoNameSearch = Off
+settings.slideShowOption = Off
+
+; default Flexy Options for this application
+flexyOptions.templateDir = BASE "Toolkit/Photos/templates"
+flexyOptions.compileDir = BASE "Toolkit/Photos/templates/compiled"
+flexyOptions.url_rewrite = "baseurl/::" BASE_URL ",basesecureurl/::" BASE_SECURE_URL ",glmappbaseurl/::" GLM_APP_BASE_URL
+flexyOptions.forceCompile = Off
+flexyOptions.locale = "en"
+flexyOptions.debug = Off
+flexyOptions.allowPHP = On
+flexyOptions.flexyIgnore = On
+flexyOptions.globals = On
+flexyOptions.globalfunctions = On
+flexyOptions.privates = On
+flexyOptions.compiler = "Flexy"
+
+; development server configuration data inherits from production and
+; overrides values as necessary
+[development : production]
+
+; chuck's server configuration data inherits from development
+; and overrides values as necessary
+[chuck : development]
+
+; john's server configuration data inherits from development
+; and overrides values as necessary
+[john : development]
+
+; steve's server configuration data inherits from development
+; and overrides values as necessary
+[steve : development]
--- /dev/null
+.header {
+ margin: 10px 20px;
+ }
+#photo-gallery {
+ margin: 10px 20px;
+}
+#glmMediaGallery {
+ background: #F5F3E5;
+ border-width: 0 1px 1px;
+ border: 1px solid #A6C9E2;
+ padding: 15px;
+}
+div.thumb {
+ margin: 3px 9px;
+ border: 0px solid #A0ACC0;
+ height: auto;
+ float: left;
+ text-align: center;
+}
+.thumb img{
+ display: inline;
+ margin: 3px;
+ border: 1px solid #A0ACC0;
+ }
+.thumb a:hover img {border: 1px solid black;}
+.photocattitle {text-align: center; font-weight: bold;}
+.phototitle {text-align: center; font-weight: normal; width: 110px;}
+.galleryRow {clear: left;}
--- /dev/null
+.containerobj .widget {
+ background-color: white;
+}
+.containerobj .active .widget {
+ color: white;
+ background-color: #3671cf;
+}
+.containerobj .inpath .widget {
+ background-color: #d0d0d0;
+}
+#demo1 {
+ height: 200px;
+}
+#demo1 a {
+ padding: 0 3px;
+}
+.ui-dialog-buttonpane {
+ padding: 0 10px 0 20px !important;
+}
+#dialog-modal {
+ height: auto !important;
+}
+
+#addPageTo {
+ /*display: inline;
+ width: 82px;
+ height: 28px;
+ border: none;
+ text-align: left;
+ padding: 0 0 0 24px;*/
+ margin: 6px 0 0 0;
+ float: right;
+}
+#deleteBtn2 {
+ display: block;
+ position:absolute;
+ bottom: 36px;
+ right: 5px;
+ width: 55px;
+ height: 28px;
+ background: url(../assets/btn_delete.gif) no-repeat;
+ border: none;
+ padding: 0 0 0 27px;
+ font-size: 14px;
+ font-size: 1.4rem;
+ line-height: 28px;
+ text-decoration: none;
+ margin: 0px;
+}
+.ui-state-highlight {
+ color: #09F;
+ border-color: #09F;
+ background: #09F;
+}
+.ui-widget-content {
+ margin: 0;
+ padding: 0;
+}
+#photoGalleryFooter {
+ display: none;
+ padding: 10px;
+ text-align: center;
+ width: 100%;
+ float: bottom;
+}
+
+/* Search Form styles */
+#photoAdminSearch input[type="search"],
+ #categoryAdminSearch select {
+ height: 26px;
+ font-size: 18px;
+ width: 300px;
+ border: 1px solid #CCCCCC;
+ background-color: #EFEFEF !important;
+ }
+ #mediaGallerySearchForm {
+ padding: 0;
+ margin: 20px 0 20px;
+ }
+ #categorySearchWrapper {
+ width: 800px;
+ height: 34px;
+ position: relative;
+ border-bottom: 1px solid #CCC;
+ }
+ #categoryAdminSearch select {
+ display: block;
+ position: relative;
+ float: left;
+ z-index: 99;
+ left: 0;
+ top: 0;
+ width: 37.75%;
+ margin: 0 .5% 0 0;
+ font-size: 14px;
+ font-weight: normal;
+ color: #666;
+ height: 27px;
+ -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
+ -moz-box-sizing: border-box; /* Firefox, other Gecko */
+ box-sizing: border-box; /* Opera/IE 8+ */
+ padding:.2em;/.3em;
+ }
+ #categoryAdminSearch input[type="submit"], #photoAdminSearch input[type="submit"] {
+ display: block;
+ position: relative;
+ float: left;
+ z-index: 99;
+ right: 0;
+ top: 0;
+ width: 10%;
+ margin: 0;
+ font-size: 14px;
+ font-weight: normal;
+ color: #666;
+ margin: 0;
+ height: 28px;
+ -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
+ -moz-box-sizing: border-box; /* Firefox, other Gecko */
+ box-sizing: border-box; /* Opera/IE 8+ */
+ }
+ #photoAdminSearch input[type="search"] {
+ display: block;
+ position: relative;
+ float: left;
+ z-index: 99;
+ left: 0;
+ top: 0;
+ width: 37.75%;
+ margin: 0 .5% 0 3%;
+ font-size: 14px;
+ font-weight: normal;
+ color: #333;
+ height: 27px;
+ -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
+ -moz-box-sizing: border-box; /* Firefox, other Gecko */
+ box-sizing: border-box; /* Opera/IE 8+ */
+ padding:.2em;/.3em;
+ padding-left: 6px;
+ }
+ div.photo-category-list {
+ background: #EFEFEF;
+ border-radius: 5px;
+ display: block;
+ float: left;
+ height: 148px;
+ margin: 0 20px 20px 0;
+ padding: 10px;
+ position: relative;
+ width: 120px;
+ border: 1px solid #CCC;
+ -webkit-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
+ box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
+ }
+ div.pCount {
+ background-color: #333;
+ border-radius: 30px 30px 30px 30px;
+ -webkit-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
+ box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
+ color: white;
+ display: inline;
+ float: right;
+ font-weight: bold;
+ padding: 1px 5px;
+ position: absolute;
+ right: -8px;
+ text-shadow: 1px 1px grey;
+ top: 0;
+ }
+ div.photo-category-list h1 {
+ bottom: 10px;
+ left: 10px;
+ margin: 0;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 123px;
+ }
+ div.photo-category-list img {
+ border: medium none;
+ border-radius: 5px;
+ -webkit-box-shadow: inset 0px 0px 5px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: inset 0px 0px 5px rgba(0, 0, 0, 0.2);
+ box-shadow: inset 0px 0px 5px rgba(0, 0, 0, 0.2);
+ border: 1px solid #CCC;
+ }
+
+/* edit category form styles */
+#editCategoryForm .webform {
+ margin: 10px 0;
+ width: 400px;
+ border: 1px solid #CCC;
+ border-radius: 5px;
+ padding: 10px 2%;
+ }
+ #editCategoryForm .webform td {
+ width: 100%;
+ float: left;
+ border: 0;
+ text-align: left;
+ }
+ #editCategoryForm .webform td input[type="text"] {
+ display: block;
+ position: relative;
+ z-index: 99;
+ left: 0;
+ top: 0;
+ width: 100%;
+ margin: 0;
+ font-size: 14px;
+ font-weight: normal;
+ color: #333;
+ height: 27px;
+ -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
+ -moz-box-sizing: border-box; /* Firefox, other Gecko */
+ box-sizing: border-box; /* Opera/IE 8+ */
+ padding:.2em;/.3em;
+ padding-left: 6px;
+ background: #EFEFEF !important;
+ border: 1px solid #CCC;
+ }
+ .category-category-list {
+ position: relative;
+ box-shadow: 1px 2px 2px grey;
+ border-radius: 10px;
+ -moz-border-radius: 10px;
+ -webkit-border-radius: 10px;
+ display:block;
+ width: 120px;
+ float: left;
+ background: #D6DFC3;
+ margin: 5px;
+ padding: 10px;
+ height: 130px;
+ }
+ .category-category-list h1 {
+ position: absolute;
+ bottom: 0;
+ left: 5px;
+ margin: 0;
+ padding: 0;
+ overflow: hidden;
+ width: 123px;;
+ }
+ .category-category-list h1 a {
+ color: #006BB4;
+ font-size: 12px;
+ text-decoration: none;
+ padding: 0;
+ margin: 0;
+ overflow: hidden;
+ white-space: nowrap;
+ }
+ .category-category-list img {
+ box-shadow: 1px 2px 2px grey;
+ border-radius: 10px;
+ -moz-border-radius: 10px;
+ -webkit-border-radius: 10px;
+ border: none;
+ }
+ #addPageTo, form#editCategoryForm input[type="submit"] {
+ /*box-shadow: 1px 2px 2px grey;
+ background-color: #D6DFC3;
+ font-size: 16px;
+ font-weight: normal;
+ text-align: center;
+ margin: 0;
+ padding: 1px 5px 1px 5px;
+ width: auto;*/
+ }
+ .pageLink {
+ /*border-radius: 10px;*/
+ /*box-shadow: 1px 2px 2px grey;
+ width: 280px;
+ background-color: #D6DFC3;
+ padding: 5px;
+ margin: 5px 0;
+ float: left;*/
+ width: 96%;
+ padding: 5px 2%;
+ border-bottom: 1px solid #CCC;
+ }
+ .btnDelete {
+ float: right;
+ }
+ #displayWrapper {
+ margin: 3px 0;
+ border-left: 1px solid #CCC;
+ border-right: 1px solid #CCC;
+ border-top: 1px solid #CCC;
+ background: #EFEFEF;
+ }
+ #categorySave {
+ width: 31.333333%;
+ margin: 0 2% 0 0;
+ }
+ #categoryCancel {
+ width: 31.333333%;
+ margin: 0 2% 0 0;
+ }
+ #categoryDelete {
+ width: 31.333333%;
+ margin: 0;
+ }
+ #pagesLabel {
+ padding-top: 5px;
+ }
+ div.category-category-list {
+ background: #EFEFEF;
+ border-radius: 5px;
+ display: block;
+ float: left;
+ height: 148px;
+ margin: 0 20px 20px 0;
+ padding: 10px;
+ position: relative;
+ width: 120px;
+ border: 1px solid #CCC;
+ -webkit-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
+ box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
+ }
+ div.category-category-list h1 {
+ bottom: 10px;
+ left: 10px;
+ margin: 0;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 123px;
+ }
+ div.category-category-list img {
+ border: medium none;
+ border-radius: 5px;
+ -webkit-box-shadow: inset 0px 0px 5px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: inset 0px 0px 5px rgba(0, 0, 0, 0.2);
+ box-shadow: inset 0px 0px 5px rgba(0, 0, 0, 0.2);
+ border: 1px solid #CCC;
+ }
+ div#categoryPhotos {
+ margin-top: 20px;
+ }
--- /dev/null
+/* ----------------------------------------------------------------------------------------------------------------*/
+/* ---------->>> global settings needed for thickbox <<<-----------------------------------------------------------*/
+/* ----------------------------------------------------------------------------------------------------------------*/
+/* *{padding: 0; margin: 0;} */
+
+/* ----------------------------------------------------------------------------------------------------------------*/
+/* ---------->>> thickbox specific link and font settings <<<------------------------------------------------------*/
+/* ----------------------------------------------------------------------------------------------------------------*/
+#TB_window {
+ font: 12px Arial, Helvetica, sans-serif;
+ color: #333333;
+}
+
+#TB_secondLine {
+ font: 10px Arial, Helvetica, sans-serif;
+ color:#666666;
+}
+
+#TB_window a:link {color: #666666;}
+#TB_window a:visited {color: #666666;}
+#TB_window a:hover {color: #000;}
+#TB_window a:active {color: #666666;}
+#TB_window a:focus{color: #666666;}
+
+/* ----------------------------------------------------------------------------------------------------------------*/
+/* ---------->>> thickbox settings <<<-----------------------------------------------------------------------------*/
+/* ----------------------------------------------------------------------------------------------------------------*/
+#TB_overlay {
+ position: fixed;
+ z-index:100;
+ top: 0px;
+ left: 0px;
+ height:100%;
+ width:100%;
+}
+
+.TB_overlayMacFFBGHack {background: url(macFFBgHack.png) repeat;}
+.TB_overlayBG {
+ background-color:#000;
+ filter:alpha(opacity=75);
+ -moz-opacity: 0.75;
+ opacity: 0.75;
+}
+
+* html #TB_overlay { /* ie6 hack */
+ position: absolute;
+ height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');
+}
+
+#TB_window {
+ position: fixed;
+ background: #ffffff;
+ z-index: 102;
+ color:#000000;
+ display:none;
+ border: 4px solid #525252;
+ text-align:left;
+ top:50%;
+ left:50%;
+}
+
+* html #TB_window { /* ie6 hack */
+position: absolute;
+margin-top: expression(0 - parseInt(this.offsetHeight / 2) + (TBWindowMargin = document.documentElement && document.documentElement.scrollTop || document.body.scrollTop) + 'px');
+}
+
+#TB_window img#TB_Image {
+ display:block;
+ margin: 15px 0 0 15px;
+ border-right: 1px solid #ccc;
+ border-bottom: 1px solid #ccc;
+ border-top: 1px solid #666;
+ border-left: 1px solid #666;
+}
+
+#TB_caption{
+/* height:25px; */
+ padding:7px 30px 10px 25px;
+ float:left;
+}
+
+#TB_DownloadLinks {
+ padding:7px 30px 10px 25px;
+ float:left;
+}
+
+#TB_closeWindow{
+ height:25px;
+ padding:11px 25px 10px 0;
+ float:right;
+}
+
+#TB_closeAjaxWindow{
+ padding:7px 10px 5px 0;
+ margin-bottom:1px;
+ text-align:right;
+ float:right;
+}
+
+#TB_ajaxWindowTitle{
+ float:left;
+ padding:7px 0 5px 10px;
+ margin-bottom:1px;
+}
+
+#TB_title{
+ background-color:#e8e8e8;
+ height:27px;
+}
+
+#TB_ajaxContent{
+ clear:both;
+ padding:2px 15px 15px 15px;
+ overflow:auto;
+ text-align:left;
+ line-height:1.4em;
+}
+
+#TB_ajaxContent.TB_modal{
+ padding:15px;
+}
+
+#TB_ajaxContent p{
+ padding:5px 0px 5px 0px;
+}
+
+#TB_load{
+ position: fixed;
+ display:none;
+ height:13px;
+ width:208px;
+ z-index:103;
+ top: 50%;
+ left: 50%;
+ margin: -6px 0 0 -104px; /* -height/2 0 0 -width/2 */
+}
+
+* html #TB_load { /* ie6 hack */
+position: absolute;
+margin-top: expression(0 - parseInt(this.offsetHeight / 2) + (TBWindowMargin = document.documentElement && document.documentElement.scrollTop || document.body.scrollTop) + 'px');
+}
+
+#TB_HideSelect{
+ z-index:99;
+ position:fixed;
+ top: 0;
+ left: 0;
+ background-color:#fff;
+ border:none;
+ filter:alpha(opacity=0);
+ -moz-opacity: 0;
+ opacity: 0;
+ height:100%;
+ width:100%;
+}
+
+* html #TB_HideSelect { /* ie6 hack */
+ position: absolute;
+ height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');
+}
+
+#TB_iframeContent{
+ clear:both;
+ border:none;
+ margin-bottom:-1px;
+ margin-top:1px;
+ _margin-bottom:1px;
+}
--- /dev/null
+/**
+ * jquery.columnview-1.2.js
+ *
+ * Created by Chris Yates on 2009-02-26.
+ * http://christianyates.com
+ * Copyright 2009 Christian Yates and ASU Mars Space Flight Facility. All rights reserved.
+ *
+ * Supported under jQuery 1.2.x or later
+ * Keyboard navigation supported under 1.3.x or later
+ *
+ * Dual licensed under MIT and GPL.
+ */
+
+(function($){
+ $.fn.columnview = function(options){
+
+ var settings = $.extend({}, $.fn.columnview.defaults, options);
+
+ // Add stylesheet, but only once
+ if(!$('.containerobj').get(0)){
+ $('head').prepend('\
+ <style type="text/css" media="screen">\
+ .containerobj {\
+ border: 1px solid #ccc;\
+ height:5em;\
+ overflow-x:auto;\
+ overflow-y:hidden;\
+ white-space:nowrap;\
+ position:relative;\
+ }\
+ .containerobj div {\
+ height:100%;\
+ overflow-y:scroll;\
+ overflow-x:hidden;\
+ position:absolute;\
+ }\
+ .containerobj a {\
+ display:block;\
+ white-space:nowrap;\
+ clear:both;\
+ padding-right:15px;\
+ overflow:hidden;\
+ text-decoration:none;\
+ }\
+ .containerobj a:focus {\
+ outline:none;\
+ }\
+ .containerobj a canvas {\
+ }\
+ .containerobj .feature {\
+ min-width:200px;\
+ overflow-y:auto;\
+ }\
+ .containerobj .feature a {\
+ white-space:normal;\
+ }\
+ .containerobj .hasChildMenu {\
+ }\
+ .containerobj .active {\
+ background-color:#3671cf;\
+ color:#fff;\
+ }\
+ .containerobj .inpath {\
+ background-color:#d0d0d0;\
+ color:#000;\
+ }\
+ .containerobj .hasChildMenu .widget {\
+ color:black;\
+ position:absolute;\
+ right:0;\
+ text-decoration:none;\
+ font-size:0.7em;\
+ }\
+ </style>');
+ }
+
+ // Hide original list
+ $(this).hide();
+ // Reset the original list's id
+ var origid = $(this).attr('id');
+ if (origid) {
+ $(this).attr('id', origid + "-processed");
+ }
+
+ // Create new top container from top-level LI tags
+ var top = $(this).children('li');
+ var container = $('<div/>').addClass('containerobj').attr('id', origid).insertAfter(this);
+ var topdiv = $('<div class="top"></div>').appendTo(container);
+ // Set column width
+ if (settings.fixedwidth || $.browser.msie) { // MSIE doesn't support auto-width
+ var width = typeof settings.fixedwidth == "string" ? settings.fixedwidth : '200px';
+ $('.top').width(width);
+ }
+ $.each(top,function(i,item){
+ var topitem = $(':eq(0)',item).clone(true).wrapInner("<span/>").data('sub',$(item).children('ul')).appendTo(topdiv);
+ if (settings.fixedwidth || $.browser.msie)
+ $(topitem).css({'text-overflow':'ellipsis', '-o-text-overflow':'ellipsis','-ms-text-overflow':'ellipsis'});
+ if($(topitem).data('sub').length) {
+ $(topitem).addClass('hasChildMenu');
+ addWidget(container, topitem);
+ }
+ });
+
+ // Firefox doesn't repeat keydown events when the key is held, so we use
+ // keypress with FF/Gecko/Mozilla to enable continuous keyboard scrolling.
+ var key_event = $.browser.mozilla ? 'keypress' : 'keydown';
+
+ // Event handling functions
+ $(container).bind("click " + key_event, function(event){
+ if ($(event.target).is("a,span")) {
+ if ($(event.target).is("span")){
+ var self = $(event.target).parent();
+ }
+ else {
+ var self = event.target;
+ }
+ if (!settings.multi) {
+ delete event.shiftKey;
+ delete event.metaKey;
+ }
+ self.focus();
+ var container = $(self).parents('.containerobj');
+ // Handle clicks
+ if (event.type == "click"){
+ var level = $('div',container).index($(self).parents('div'));
+ var isleafnode = false;
+ // Remove blocks to the right in the tree, and 'deactivate' other
+ // links within the same level, if metakey is not being used
+ $('div:gt('+level+')',container).remove();
+ if (!event.metaKey && !event.shiftKey) {
+ $('div:eq('+level+') a',container).removeClass('active').removeClass('inpath');
+ $('.active',container).addClass('inpath');
+ $('div:lt('+level+') a',container).removeClass('active');
+ }
+ // Select intermediate items when shift clicking
+ // Sorry, only works with jQuery 1.4 due to changes in the .index() function
+ if (event.shiftKey) {
+ var first = $('a.active:first', $(self).parent()).index();
+ var cur = $(self).index();
+ var range = [first,cur].sort(function(a,b){return a - b;});
+ $('div:eq('+level+') a', container).slice(range[0], range[1]).addClass('active');
+ }
+ $(self).addClass('active');
+ if ($(self).data('sub').children('li').length && !event.metaKey) {
+ // Menu has children, so add another submenu
+ var w = false;
+ if (settings.fixedwidth || $.browser.msie)
+ w = typeof settings.fixedwidth == "string" ? settings.fixedwidth : '200px';
+ submenu(container,self,w);
+ }
+ else if (!event.metaKey && !event.shiftKey) {
+ // No children, show title instead (if it exists, or a link)
+ isleafnode = true;
+ var previewcontainer = $('<div/>').addClass('feature').appendTo(container);
+ // Fire preview handler function
+ if ($.isFunction(settings.preview)) {
+ // We're passing the element back to the callback
+ var preview = settings.preview($(self));
+ }
+ // If preview is specifically disabled, do nothing with the previewbox
+ else if (!settings.preview) {
+ }
+ // If no preview function is specificied, use a default behavior
+ else {
+ var title = $('<a/>').attr({href:$(self).attr('href')}).text($(self).attr('title') ? $(self).attr('title') : $(self).text());
+ $(previewcontainer).html(title);
+ }
+ // Set the width
+ var remainingspace = 0;
+ $.each($(container).children('div').slice(0,-1),function(i,item){
+ remainingspace += $(item).width();
+ });
+ var fillwidth = $(container).width() - remainingspace;
+ $(previewcontainer).css({'top':0,'left':remainingspace}).width(fillwidth).show();
+ }
+ // Fire onchange handler function, but only if multi-select is off.
+ // FIXME Need to deal multiple selections.
+ if ($.isFunction(settings.onchange) && !settings.multi) {
+ // We're passing the element back to the callback
+ var onchange = settings.onchange($(self), isleafnode);
+ }
+ }
+ // Handle Keyboard navigation
+ if(event.type == key_event){
+ switch(event.keyCode){
+ case(37): //left
+ $(self).parent().prev().children('.inpath').focus().trigger("click");
+ break;
+ case(38): //up
+ $(self).prev().focus().trigger("click");
+ break;
+ case(39): //right
+ if($(self).hasClass('hasChildMenu')){
+ $(self).parent().next().children('a:first').focus().trigger("click");
+ }
+ break;
+ case(40): //down
+ $(self).next().focus().trigger("click");
+ break;
+ case(13): //enter
+ $(self).trigger("dblclick");
+ break;
+ }
+ }
+ event.preventDefault();
+ }
+ });
+
+ };
+
+ $.fn.columnview.defaults = {
+ multi: false, // Allow multiple selections
+ preview: true, // Handler for preview pane
+ fixedwidth: false,// Use fixed width columns
+ onchange: false // Handler for selection change
+ };
+
+ // Generate deeper level menus
+ function submenu(container,item,width){
+ var leftPos = 0;
+ $.each($(container).children('div'),function(i,mydiv){
+ leftPos += $(mydiv).width();
+ });
+ var submenu = $('<div/>').css({'top':0,'left':leftPos}).appendTo(container);
+ // Set column width
+ if (width)
+ $(submenu).width(width);
+ var subitems = $(item).data('sub').children('li');
+ $.each(subitems,function(i,subitem){
+ var subsubitem = $(':eq(0)',subitem).clone(true).wrapInner("<span/>").data('sub',$(subitem).children('ul')).appendTo(submenu);
+ if (width)
+ $(subsubitem).css({'text-overflow':'ellipsis', '-o-text-overflow':'ellipsis','-ms-text-overflow':'ellipsis'});
+ if($(subsubitem).data('sub').length) {
+ $(subsubitem).addClass('hasChildMenu');
+ addWidget(container, subsubitem);
+ }
+ });
+ }
+
+ // Uses canvas, if available, to draw a triangle to denote that item is a parent
+ function addWidget(container, item, color){
+ var triheight = $(item).height();
+ var canvas = $("<canvas></canvas>").attr({height:triheight,width:10}).addClass('widget').appendTo(item); if(!color){ color = $(canvas).css('color'); }
+ canvas = $(canvas).get(0);
+ if(canvas.getContext){
+ var context = canvas.getContext('2d');
+ context.fillStyle = color;
+ context.beginPath();
+ context.moveTo(3,(triheight/2 - 3));
+ context.lineTo(10,(triheight/2));
+ context.lineTo(3,(triheight/2 + 3));
+ context.fill();
+ } else {
+ /**
+ * Canvas not supported - put something in there anyway that can be
+ * suppressed later if desired. We're using a decimal character here
+ * representing a "black right-pointing pointer" in Windows since IE
+ * is the likely case that doesn't support canvas.
+ */
+ $("<span>►</span>").addClass('widget').css({'height':triheight,'width':10}).prependTo(item);
+ }
+ $(container).find('.widget').bind('click', function(event){
+ event.preventDefault();
+ });
+
+ }
+})(jQuery);
\ No newline at end of file
--- /dev/null
+$(function(){
+ $("#photoCategoryId").change(function(){
+ $(this).parent().submit();
+ });
+});
+
+(function(window, PhotoSwipe){
+ //if ($(".photoimg").length > 0) {
+ if(document.addEventListener) {
+ document.addEventListener('DOMContentLoaded', function(){
+ var
+ options = {
+ getImageCaption: function(el){
+ var captionText, captionDesc, captionId, captionEl;
+
+ if (el.nodeName === "A") {
+ captionText = el.getAttribute('title');
+ captionDesc = el.getAttribute('rel');
+ captionId = el.getAttribute('data-photoid');
+ captionDownload = el.getAttribute('data-download');
+ }
+
+ // Return a DOM element with custom styling
+ if((captionText != null && captionText != "") || (captionDesc != null && captionDesc != "")) {
+ captionEl = document.createElement('div');
+ captionEl.className = 'captionWrapper';
+ // Add Caption Title.
+ if(captionText != null && captionText != "") {
+ captionTitleOutput = document.createElement('h2');
+ captionTitleOutput.className = "captionTitleWrapper";
+ captionTitleOutput.appendChild(document.createTextNode(captionText));
+ captionEl.appendChild(captionTitleOutput);
+ }
+ // Add Caption Description.
+ if(captionDesc != null && captionDesc != "") {
+ captionDescOutput = document.createElement('p');
+ captionDescOutput.className = "captionDescWrapper";
+ captionDescOutput.appendChild(document.createTextNode(captionDesc));
+ captionEl.appendChild(captionDescOutput);
+ }
+ } else {
+ //captionEl = document.createElement('div');
+ //captionEl.style.cssText = 'display:none; width:0; height:0;';
+ captionEl = "";
+ }
+ // Add Download links.
+ if(captionId != null && captionId != "" && captionDownload == "1") {
+ captionIdOutput = document.createElement('div');
+ captionIdOutput.className = 'download_wrapper';
+ captionEl.appendChild(captionIdOutput);
+ // Add Link Text.
+ captionLinkText = document.createElement('span');
+ captionText = document.createTextNode("Download for ");
+ captionLinkText.appendChild(captionText);
+ captionIdOutput.appendChild(captionLinkText);
+ // Add Web Link.
+ captionWebLink = base_url + "download-photo-web/" + captionId + "/";
+ downloadWebLink = document.createElement('a');
+ linkText = document.createTextNode("Web");
+ downloadWebLink.appendChild(linkText);
+ downloadWebLink.title = "Download for Web";
+ downloadWebLink.href = captionWebLink;
+ captionIdOutput.appendChild(downloadWebLink);
+ // Add Spacer Text.
+ captionSpacerText = document.createElement('span');
+ captionText = document.createTextNode(" - ");
+ captionSpacerText.appendChild(captionText);
+ captionIdOutput.appendChild(captionSpacerText);
+ // Add Print Link.
+ captionPrintLink = base_url + "download-photo-print/" + captionId + "/";
+ downloadPrintLink = document.createElement('a');
+ linkPrintText = document.createTextNode("Print");
+ downloadPrintLink.appendChild(linkPrintText);
+ downloadPrintLink.title = "Download for Print";
+ downloadPrintLink.href = captionPrintLink;
+ captionIdOutput.appendChild(downloadPrintLink);
+ }
+
+ return captionEl;
+
+ // Alternatively you can just pass back a string. However, any HTML
+ // markup will be escaped
+
+ }, captionAndToolbarAutoHideDelay:0, imageScaleMethod: "fitNoUpscale", captionAndToolbarFlipPosition: true, backButtonHideEnabled: true
+ },
+ instance = PhotoSwipe.attach( window.document.querySelectorAll('a.photoimg'), options );
+ }, false);
+ } else { // You are using IE8- and you should feel bad.
+ document.attachEvent('onreadystatechange', function(){
+ var
+ options = {
+ getImageCaption: function(el){
+ var captionText, captionDesc, captionId, captionEl;
+
+ if (el.nodeName === "A") {
+ captionText = el.getAttribute('title');
+ captionDesc = el.getAttribute('rel');
+ captionId = el.getAttribute('data-photoid');
+ captionDownload = el.getAttribute('data-download');
+ }
+
+ // Return a DOM element with custom styling
+ if((captionText != null && captionText != "") || (captionDesc != null && captionDesc != "")) {
+ //captionEl = document.createElement('div');
+ captionEl = $('<div style="display: block;width: 100%;overflow: hidden;"></div>');
+ captionEl.addClass = 'captionWrapper';
+ // Add Caption Title.
+ if(captionText != null && captionText != "") {
+ //captionTitleOutput = document.createElement('h2');
+ captionTitleOutput = $('<h2 style="display: block;width: 50%;float: left;font-size: 18px;font-weight: bold;color: #FFF;text-align: left;padding: 10px 20px;margin: 0;"></h2>');
+ captionTitleOutput.addClass = "captionTitleWrapper";
+ captionTitleOutput.append(captionText);
+ captionEl.append(captionTitleOutput);
+ }
+ // Add Caption Description.
+ if(captionDesc != null && captionDesc != "") {
+ //captionDescOutput = document.createElement('p');
+ captionDescOutput = $('<p style="display: block;width: 50%;float: left;clear: left;font-size: 14px;color: #FFF;text-align: left;padding: 0 20px 10px 20px;margin: 0;"></p>');
+ captionDescOutput.addClass = "captionDescWrapper";
+ captionDescOutput.append(document.createTextNode(captionDesc));
+ captionEl.append(captionDescOutput);
+ }
+ } else {
+ //captionEl = document.createElement('div');
+ //captionEl.style.cssText = 'display:none; width:0; height:0;';
+ captionEl = "";
+ }
+ // Add Download links.
+ if(captionId != null && captionId != "" && captionDownload == "1") {
+ captionIdOutput = $('<div style="display: block;position: absolute;z-index: 99;top: 10px;right: 20px;width: 30%;font-size: 14px;color: #FFF;text-align: left;padding: 6px 0 10px 20px;margin: 0;text-align: right;"></div>');
+ captionIdOutput.addClass = 'download_wrapper';
+ captionEl.append(captionIdOutput);
+ // Add Link Text.
+ captionLinkText = $('<span></span>');
+ captionText = document.createTextNode("Download for ");
+ captionLinkText.append(captionText);
+ captionIdOutput.append(captionLinkText);
+ // Add Web Link.
+ captionWebLink = base_url + "download-photo-web/" + captionId + "/";
+ downloadWebLink = $('<a style="color: #CCC;"></a>');
+ linkText = document.createTextNode("Web");
+ downloadWebLink.append(linkText);
+ downloadWebLink.title = "Download for Web";
+ downloadWebLink.attr('href', captionWebLink);
+ captionIdOutput.append(downloadWebLink);
+ // Add Spacer Text.
+ captionSpacerText = $('<span></span>');
+ captionText = document.createTextNode(" - ");
+ captionSpacerText.append(captionText);
+ captionIdOutput.append(captionSpacerText);
+ // Add Print Link.
+ captionPrintLink = base_url + "download-photo-print/" + captionId + "/";
+ downloadPrintLink = $('<a style="color: #CCC;"></a>');
+ linkPrintText = document.createTextNode("Print");
+ downloadPrintLink.append(linkPrintText);
+ downloadPrintLink.title = "Download for Print";
+ downloadPrintLink.attr('href', captionPrintLink);
+ captionIdOutput.append(downloadPrintLink);
+ }
+
+ return captionEl;
+
+ // Alternatively you can just pass back a string. However, any HTML
+ // markup will be escaped
+
+ }, captionAndToolbarAutoHideDelay:0, imageScaleMethod: "fitNoUpscale", captionAndToolbarFlipPosition: true, backButtonHideEnabled: true
+ },
+ instance = PhotoSwipe.attach( window.document.querySelectorAll('a.photoimg'), options );
+ }, false);
+ }
+ //}
+}(window, window.Code.PhotoSwipe));
+
--- /dev/null
+<?php
+require_once '../../setup.phtml';
+
+HTTP_Session2::useCookies(false);
+HTTP_Session2::start();
+
+$catid = filter_var($_REQUEST['catid'], FILTER_VALIDATE_INT);
+$dbh = Toolkit_Database::getInstance();
+$authContainer = new Toolkit_Photos_AuthContainer($dbh);
+$photoAuth = new Toolkit_Photos_Auth(
+ $authContainer,
+ '',
+ false
+);
+$photoAuth->start();
+
+if (isset($_REQUEST['logout'])) {
+ $photoAuth->logout();
+ header('Location: ' . BASE_URL . 'index.php?catid=' . $catid);
+ exit;
+}
+
+if (!$photoAuth->checkAuth()) {
+ // see if the user exists but has expired
+ $userName = filter_var($_REQUEST['username'], FILTER_SANITIZE_STRING);
+ $passWord = filter_var($_REQUEST['password'], FILTER_SANITIZE_STRING);
+ $status = $photoAuth->getStatus();
+ if ($passWord && $userName) {
+ try {
+ $sql = "
+ SELECT id
+ FROM contacts.contact
+ WHERE email = :uname
+ AND media_pass = :pword
+ AND media = true
+ AND approved = true
+ AND expire < current_date";
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(':uname', $userName, PDO::PARAM_STR);
+ $stmt->bindParam(':pword', $passWord, PDO::PARAM_STR);
+ $stmt->execute();
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+ if ($row !== FALSE) {
+ $status = -4;
+ }
+ } catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+ // Manually adjust the authentication status for empty credentials
+ if (empty($_POST['username']) || empty($_POST['password'])) {
+ $status = -3;
+ }
+ header('Location: '
+ . BASE_URL . 'index.php?catid=' . $catid . '&status=' . $status);
+ exit;
+} else {
+ header('Location: ' . BASE_URL . 'index.php?catid=' . $catid);
+}
--- /dev/null
+<?php
+require_once '../../setup.phtml';
+
+HTTP_Session2::useCookies(false);
+HTTP_Session2::start();
+$dbh = Toolkit_Database::getInstance();
+$catid = filter_var($_REQUEST['catid'], FILTER_VALIDATE_INT);
+$authContainer = new Toolkit_Photos_AuthContainer($dbh);
+
+$photoAuth = new Auth(
+ $authContainer,
+ array(
+ 'sessionName' => 'glmMedia',
+ 'allowLogin' => true,
+ 'dbFields' => array('id', 'fname', 'lname')
+ ),
+ '',
+ false
+);
+$photoAuth->setIdle(86400, true);
+$photoAuth->start();
+//var_dump($_REQUEST);
+
+// get image name from db
+$photoId = filter_var($_REQUEST['photo_id'], FILTER_VALIDATE_INT);
+if (!$photoId) {
+ die('Sorry no image found');
+}
+$isAuthorized = $photoAuth->checkAuth();
+try {
+ // here we'll need to also check to make sure that if they're not
+ // logged in they cannot get the exclusive photos.
+ $where
+ = (!$isAuthorized)
+ ? "AND exclusive <> true"
+ : '';
+ $sql = "
+ SELECT image
+ FROM photo
+ WHERE id = :id
+ $where";
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(':id', $photoId, PDO::PARAM_INT);
+ $stmt->execute();
+ $imageName = $stmt->fetchColumn();
+ if (!$imageName) {
+ return false;
+ }
+} catch (PDOException $e) {
+ Toolkit_Common::handleError($e);
+}
+//var_dump($imageName);
+//exit;
+if (!$isAuthorized) {
+ // use watermarked image style
+ $style = ($_REQUEST['type'] == 'print') ? 'downPrint': 'downWeb';
+ $fileUrlPath = FILE_SERVER_URL . IS_OWNER_ID . "/{$style}/{$imageName}";
+
+ $ch = curl_init($fileUrlPath);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 50);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ $imageResponse = curl_exec($ch);
+ if (!curl_errno($ch)) {
+ $bytes = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
+ header("Pragma: public");
+ header("Expires: 0");
+ header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
+ header("Content-Type: application/force-download");
+ header("Content-Type: application/octet-stream");
+ header("Content-Type: application/download");
+ header("Content-Disposition: attachment;filename=photo-" . $photoId.".jpeg");
+ header("Content-Transfer-Encoding: binary ");
+ curl_close($ch);
+ echo $imageResponse;
+ }
+
+ exit;
+} else {
+ // use style without watermarks
+ $style = ($_REQUEST['type'] == 'print') ? 'downPrintMedia': 'downWebMedia';
+ $fileUrlPath = FILE_SERVER_URL . IS_OWNER_ID . "/{$style}/{$imageName}";
+ $ch = curl_init($fileUrlPath);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 50);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ $imageResponse = curl_exec($ch);
+ header("Pragma: public");
+ header("Expires: 0");
+ header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
+ header("Content-Type: application/force-download");
+ header("Content-Type: application/octet-stream");
+ header("Content-Type: application/download");
+ header("Content-Disposition: attachment;filename=photo-" . $photoId.".jpeg");
+ header("Content-Transfer-Encoding: binary ");
+ curl_close($ch);
+ echo $imageResponse;
+ exit;
+}
--- /dev/null
+<?php
+require_once '../../setup.phtml';
+$jsonData = array();
+$mediaMapper = new Toolkit_Photos_Models_MediaMapper(
+ Toolkit_Database::getInstance()
+);
+$photoSearch = filter_var($_REQUEST['photoName'], FILTER_SANITIZE_STRING);
+$pageId = filter_var($_REQUEST['pageId'], FILTER_VALIDATE_INT);
+$gallery = new Toolkit_Photos_Gallery(
+ Toolkit_Database::getInstance(),
+ new Toolkit_Photos_Display(
+ Toolkit_Database::getInstance()
+ )
+);
+$galleries = $gallery->getPageGalleries($pageId);
+
+$photos = $mediaMapper->fetchPhotosByNameAndCats(
+ $photoSearch,
+ $galleries,
+ true
+);
+if ($photos) {
+ foreach ($photos as $photo) {
+ $jsonData[] = $photo->getTitle();
+ }
+}
+echo json_encode($jsonData);
--- /dev/null
+<?php
+
+require_once '../../setup.phtml';
+
+$mediaMapper = new Toolkit_Photos_Models_MediaMapper(
+ Toolkit_Database::getInstance()
+);
+
+$mediaMapper->fixAllPhoto2Cats();
--- /dev/null
+<div id="editCategorySection">
+ <header>
+ <hgroup>
+ <h1>
+ Edit Category
+ </h1>
+ </hgroup>
+ </header>
+ <form
+ id="editCategoryForm"
+ name="editCategoryForm"
+ action="{formAction:h}"
+ flexy:ignore="yes"
+ method="post">
+ {if:category}
+ <input type="hidden" name="id" value="{category.getId()}">
+ <input type="hidden" name="pos" value="{category.getPos()}">
+ {if:!mediaExclusive}
+ <input type="hidden" name="exclusive" value="0">
+ {end:}
+ {end:}
+ <table class="webform">
+ <tr>
+ <td class="labelcell">
+ Name
+ </td>
+ <td class="fieldcell">
+ {if:category}
+ <input type="text" name="category" value="{category.getCategory()}">
+ {else:}
+ <input type="text" name="category">
+ {end:}
+ </td>
+ </tr>
+ <tr>
+ <td class="labelcell" id="pagesLabel">
+ Pages for Display
+ </td>
+ <td class="fieldcell">
+ <div id="displayWrapper">
+ <div id="pages2PhotosDiv">
+ {if:pages2Categories}
+ <div class="pageLink" flexy:foreach="pages2Categories,page">
+ <input type="hidden" name="pages[]" value="{page[page]}">
+ {page[page_name]}
+ <a href="#" class="ui-icon ui-icon-trash btnDelete">Delete</a>
+ </div>
+ {end:}
+ </div>
+ <div id="dialog-modal" title="Page Selector" style="display:none;">
+ <div id="pages"></div>
+ </div>
+ <input type="submit" id="addPageTo" value="Add Pages">
+ </div><!--/#displayWrapper-->
+ </td>
+ </tr>
+ <tr flexy:if="slideShow">
+ <td class="labelcell">
+ SlideShow Option?
+ </td>
+ <td class="fieldcell">
+ <input type="hidden" name="slideshow" value="0"><label>
+ {if:category}
+ {if:category.getSlideShow()}
+ <input type="checkbox" name="slideshow" value="1" checked>
+ {else:}
+ <input type="checkbox" name="slideshow" value="1">
+ {end:}
+ {else:}
+ <input type="checkbox" name="slideshow" value="1">
+ {end:}Yes</label>
+ </td>
+ </tr>
+ <tr flexy:if="mediaExclusive">
+ <td class="labelcell">
+ Media Exclusive?
+ </td>
+ <td class="fieldcell">
+ <input type="hidden" name="exclusive" value="0"><label>
+ {if:category}
+ {if:category.getExclusive()}
+ <input type="checkbox" name="exclusive" value="1" checked>
+ {else:}
+ <input type="checkbox" name="exclusive" value="1">
+ {end:}
+ {else:}
+ <input type="checkbox" name="exclusive" value="1">
+ {end:}Yes</label>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" align="center">
+ <input id="categorySave" type="submit" value="Save">
+ {if:category}
+ <input id="categoryCancel" type="submit" value="Cancel" name="Cancel">
+ <input id="categoryDelete" type="submit" value="Delete Category" name="Delete">
+ {end:}
+ </td>
+ </tr>
+ </table>
+ </form>
+</div>
+<div id="categoryPhotos">
+ <form id="sortable">
+ <input type="hidden" name="ac" value="movePhotos">
+ <input type="hidden" name="categoryId" value="{category.getId()}">
+ <div
+ class="category-category-list"
+ flexy:foreach="photos,photo">
+ <input type="hidden" name="photos[]" value="{photo.getId()}">
+ {if:photo.getImage()}
+ <a href="{editUrl:h}{photo.getId()}">
+ <img width="120" height="120" src="{imgPath:h}{photo.getImage():h}">
+ </a>
+ {end:}
+ <header>
+ <hgroup>
+ <h1>
+ <a href="{editUrl:h}{photo.getId()}">
+ {photo.getTitle()}
+ </a>
+ </h1>
+ </hgroup>
+ </header>
+ </div>
+ </form>
+</div>
+<script>
+ $(function(){
+ if ($("#categoryDelete").length) {
+ $("#categoryDelete").click(function(){
+ return confirm("This will Delete this Category.\nAre you sure?");
+ });
+ }
+ $('body').delegate('.btnDelete', 'click', function(){
+ $(this).parent().remove();
+ });
+ $("#sortable").sortable({
+ update: function() {
+ var inputs = $("#sortable").serialize();
+ $.get('./photos.php', inputs, console.log('positions saved'));
+ }
+ });
+ $("#addPageTo").click(function(){
+ var selectedPageId = null;
+ var selectedPageName = null;
+ $("#dialog-modal").dialog({
+ height: 240,
+ width: 800,
+ modal: true,
+ buttons: {
+ "Select Page": function() {
+ if (selectedPageId != '') {
+ // here is where it adds the page
+
+ console.log('Selected PageId: ' + selectedPageId);
+ console.log('Selected Pagename: ' + selectedPageName);
+ $("#pages2PhotosDiv").append('<div class="pageLink">'
+ + '<input type="hidden" name="pages[]" value="'
+ + selectedPageId + '">'
+ + selectedPageName
+ + '<a href="#" class="ui-icon ui-icon-trash btnDelete">Delete</a>'
+ + '</div>');
+ $(this).dialog("close");
+ } else {
+ alert("Select a Page");
+ }
+ },
+ Cancel: function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+ $("#pages").load('photos.php?ac=showPages', function(){
+ $('#demo1').columnview({
+ preview:false,
+ onchange: function(element) {
+ selectedPageId = $(element).attr('data-page');
+ selectedPageName = $(element).attr('data-name');
+ }
+ });
+ });
+ return false;
+ });
+ });
+
+</script>
--- /dev/null
+<style>
+ #editPhotoForm .webform {
+ margin: 10px 0;
+ width: 400px;
+ border: 1px solid #CCC;
+ border-radius: 5px;
+ padding: 10px 2%;
+ }
+ #editPhotoForm .webform td {
+ width: 100%;
+ float: left;
+ border: 0;
+ text-align: left;
+ }
+ #editPhotoForm .webform td input[type="text"], #editPhotoForm .webform td select {
+ display: block;
+ position: relative;
+ z-index: 99;
+ left: 0;
+ top: 0;
+ width: 100%;
+ margin: 0;
+ font-size: 14px;
+ font-weight: normal;
+ color: #333;
+ height: 27px;
+ -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
+ -moz-box-sizing: border-box; /* Firefox, other Gecko */
+ box-sizing: border-box; /* Opera/IE 8+ */
+ padding:.2em;/.3em;
+ padding-left: 6px;
+ background: #EFEFEF !important;
+ border: 1px solid #CCC;
+ }
+ ol.asmList {
+ -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
+ -moz-box-sizing: border-box; /* Firefox, other Gecko */
+ box-sizing: border-box; /* Opera/IE 8+ */
+ width: 100%;
+ border: 0;
+ background: #EFEFEF;
+ margin: 0;
+ padding: 0;
+ }
+ ol.asmList .asmListItem {
+ border: none;
+ -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
+ -moz-box-sizing: border-box; /* Firefox, other Gecko */
+ box-sizing: border-box; /* Opera/IE 8+ */
+ border-bottom: 1px solid #CCC;
+ border-right: 1px solid #CCC;
+ border-left: 1px solid #CCC;
+ padding-bottom: 5px;
+ padding-left: 6px;
+ display: block;
+ min-height: 26px;
+ background: #FFFFFF;
+ }
+ #editPhotoForm .webform textarea {
+ resize: vertical;
+ width: 98.2%;
+ max-width: 98.2%;
+ min-width: 98.2%;
+ }
+ #photoSave {
+ width: 31.333333%;
+ margin: 0 2% 0 0;
+ }
+ #photoCancel {
+ width: 31.333333%;
+ margin: 0 2% 0 0;
+ }
+ #photoDelete {
+ width: 31.333333%;
+ margin: 0;
+ }
+</style>
+<div id="editPhotoSection">
+ <header>
+ <hgroup>
+ <h1>
+ Edit Photo in {categoryName}
+ </h1>
+ </hgroup>
+ </header>
+ <form
+ id="editPhotoForm"
+ name="editPhotoForm"
+ action="{formAction:h}"
+ flexy:ignore="yes"
+ method="post"
+ enctype="multipart/form-data">
+ {if:photo}
+ <input type="hidden" name="id" value="{photo.getId()}">
+ {if:!mediaExclusive}
+ <input type="hidden" name="exclusive" value="0">
+ {end:}
+ {end:}
+ <input type="hidden" name="catid" value="{_REQUEST[catid]}">
+ <table class="webform">
+ <tr>
+ <td class="labelcell">
+ Name
+ </td>
+ <td class="fieldcell">
+ {if:photo}
+ <input type="text" name="title" value="{photo.getTitle()}">
+ {else:}
+ <input type="text" name="title">
+ {end:}
+ </td>
+ </tr>
+ <tr flexy:if="mediaExclusive">
+ <td class="labelcell">
+ Media Exclusive?
+ </td>
+ <td class="fieldcell">
+ <input type="hidden" name="exclusive" value="0"><label>
+ {if:photo}
+ {if:photo.getExclusive()}
+ <input type="checkbox" name="exclusive" value="1" checked>
+ {else:}
+ <input type="checkbox" name="exclusive" value="1">
+ {end:}
+ {else:}
+ <input type="checkbox" name="exclusive" value="1">
+ {end:}Yes</label>
+ </td>
+ </tr>
+ <tr>
+ <td class="labelcell">
+ Download?
+ </td>
+ <td class="fieldcell">
+ <input type="hidden" name="download" value="0"><label>
+ {if:photo}
+ {if:photo.getDownload()}
+ <input type="checkbox" name="download" value="1" checked>
+ {else:}
+ <input type="checkbox" name="download" value="1">
+ {end:}
+ {else:}
+ <input type="checkbox" name="download" value="1">
+ {end:}Yes</label>
+ </td>
+ </tr>
+ <tr>
+ <td class="labelcell">
+ Category
+ </td>
+ <td class="fieldcell">
+ <select
+ id="P2CSelect"
+ name="photo2Categories[]"
+ title="Select Categories"
+ multiple>
+ <?php
+ foreach ($t->categories as $category) {
+ echo '<option value="'.$category->getId().'"';
+ if ($t->photo2Categories->offsetExists($category->getId())
+ || $category->getId() == $_REQUEST['catid']
+ ) {
+ echo ' selected';
+ }
+ echo '>'.$category->getCategory().'</option>';
+ }
+ ?>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td class="labelcell">
+ Description
+ </td>
+ <td class="fieldcell">
+ {if:photo}
+ <textarea name="description">{photo.getDescription()}</textarea>
+ {else:}
+ <textarea name="description"></textarea>
+ {end:}
+ </td>
+ </tr>
+ {if:photo}
+ <tr>
+ <td class="labelcell">
+ Current Photo
+ </td>
+ <td class="fieldcell">
+ <input type="hidden" name="image" value="{photo.getImage()}">
+ <img src="{imgPath:h}{photo.getImage()}">
+ </td>
+ </tr>
+ {end:}
+ <tr>
+ <td class="labelcell">
+ New Photo
+ </td>
+ <td class="fieldcell">
+ {if:photo}
+ <input
+ id="imageUpload"
+ accept="image/*"
+ type="file"
+ name="image">
+ {else:}
+ <input
+ id="imageUpload"
+ accept="image/*"
+ type="file"
+ name="image"
+ required>
+ {end:}
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <input id="photoSave" type="submit" value="Save Photo">
+ {if:photo}
+ <input id="photoCancel" type="submit" value="Cancel" name="Cancel">
+ <input id="photoDelete" type="submit" value="Delete Photo" name="Delete">
+ {end:}
+ </td>
+ </tr>
+ </table>
+ </form>
+</div>
+<script>
+ $(function() {
+ $('INPUT[type="file"]').change(function() {
+ var ext = this.value.match(/(?:\.([^.]+))?$/)[1];
+ switch (ext.toLowerCase()) {
+ case 'jpg':
+ case 'jpeg':
+ case 'png':
+ case 'gif':
+ $('#uploadButton').attr('disabled', false);
+ break;
+ default:
+ alert('This is not an allowed file type.');
+ this.value = '';
+ }
+ });
+ $("#editPhotoForm").submit(function() {
+ var atLeastOneSeleted = false;
+ $("#P2CSelect option:selected").each(function() {
+ atLeastOneSeleted = true;
+ });
+ if (!atLeastOneSeleted) {
+ alert('You must select at least one Category');
+ }
+ return atLeastOneSeleted;
+ });
+ $("select[multiple]").asmSelect({
+ animate: true,
+ sortable: false,
+ highlight: true
+ });
+ if ($("#photoDelete").length) {
+ $("#photoDelete").click(function() {
+ return confirm("This will Delete this photo.\nAre you sure?");
+ });
+ }
+ });
+</script>
--- /dev/null
+<style>
+ form#editUserForm input[type="submit"] {
+ box-shadow: 1px 2px 2px grey;
+ border-radius: 10px;
+ background-color: #D6DFC3;
+ font-size: 16px;
+ font-weight: normal;
+ text-align: center;
+ margin: 0;
+ padding: 1px 5px 1px 5px;
+ width: auto;
+ }
+</style>
+<div>
+ <form
+ id="editUserForm"
+ name="editUserForm"
+ action="{formAction:h}"
+ flexy:ignore="yes"
+ method="post"
+ enctype="multipart/form-data">
+ <input type="hidden" name="userStatus" value="{_REQUEST[userStatus]}">
+ {if:user}
+ <input type="hidden" name="id" value="{user.getId()}">
+ {end:}
+ <table class="webform">
+ <tr>
+ <td class="labelcell">
+ Status
+ </td>
+ <td class="fieldcell">
+
+ {if:user}
+ <label>
+ {if:user.getApproved()}
+ <input type="radio" name="status" value="approved" checked>
+ {else:}
+ <input type="radio" name="status" value="approved">
+ {end:}
+ Approved
+ </label>
+ <label>
+ {if:user.getDenied()}
+ <input type="radio" name="status" value="denied" checked>
+ {else:}
+ <input type="radio" name="status" value="denied">
+ {end:}
+ Denied
+ </label>
+ {else:}
+ <label>
+ <input type="radio" name="status" value="approved">
+ Approved
+ </label>
+ <label>
+ <input type="radio" name="status" value="denied">
+ Denied
+ </label>
+
+ {end:}
+
+ </td>
+ </tr>
+ <tr>
+ <td class="labelcell">
+ Company Name
+ </td>
+ <td class="fieldcell">
+ {if:user}
+ <input name="company" value="{user.getCompany()}">
+ {else:}
+ <input name="company">
+ {end:}
+ </td>
+ </tr>
+ <tr>
+ <td class="labelcell">
+ Title
+ </td>
+ <td class="fieldcell">
+ {if:user}
+ <input name="title" value="{user.gettitle()}">
+ {else:}
+ <input name="title">
+ {end:}
+ </td>
+ </tr>
+ <tr>
+ <td class="labelcell">
+ Expire Date
+ </td>
+ <td class="fieldcell">
+ {if:user}
+ <input id="expire" name="expire" value="{user.getExpire()}">
+ {else:}
+ <input id="expire" name="expire">
+ {end:}
+ </td>
+ </tr>
+ <tr>
+ <td class="labelcell">
+ Email Address
+ </td>
+ <td class="fieldcell">
+ {if:user}
+ <input name="email" value="{user.getEmail()}" type="email" required>
+ {else:}
+ <input name="email" type="email" required>
+ {end:}
+ </td>
+ </tr>
+ <tr>
+ <td class="labelcell">
+ Password
+ </td>
+ <td class="fieldcell">
+ {if:user}
+ <input name="media_pass" value="{user.getMediaPass()}" required>
+ {else:}
+ <input name="media_pass" required>
+ {end:}
+ </td>
+ </tr>
+ <tr>
+ <td class="labelcell">
+ First Name
+ </td>
+ <td class="fieldcell">
+ {if:user}
+ <input name="fname" value="{user.getFname()}" required>
+ {else:}
+ <input name="fname">
+ {end:}
+ </td>
+ </tr>
+ <tr>
+ <td class="labelcell">
+ Last Name
+ </td>
+ <td class="fieldcell">
+ {if:user}
+ <input name="lname" value="{user.getLname()}" required>
+ {else:}
+ <input name="lname" required>
+ {end:}
+ </td>
+ </tr>
+
+ <tr>
+ <td class="labelcell">
+ Phone
+ </td>
+ <td class="fieldcell">
+ {if:user}
+ <input name="phone" value="{user.getPhone()}">
+ {else:}
+ <input name="phone">
+ {end:}
+ </td>
+ </tr>
+ <tr>
+ <td class="labelcell">
+ Address 1
+ </td>
+ <td class="fieldcell">
+ {if:user}
+ <input name="address" value="{user.getAddress()}">
+ {else:}
+ <input name="address">
+ {end:}
+ </td>
+ </tr>
+ <tr>
+ <td class="labelcell">
+ Address2
+ </td>
+ <td class="fieldcell">
+ {if:user}
+ <input name="address2" value="{user.getAddress2()}">
+ {else:}
+ <input name="address2">
+ {end:}
+ </td>
+ </tr>
+ <tr>
+ <td class="labelcell">
+ City
+ </td>
+ <td class="fieldcell">
+ {if:user}
+ <input name="city" value="{user.getCity()}">
+ {else:}
+ <input name="city">
+ {end:}
+ </td>
+ </tr>
+ <tr>
+ <td class="labelcell">
+ State
+ </td>
+ <td class="fieldcell">
+ {if:user}
+ <input name="state" value="{user.getState()}">
+ {else:}
+ <input name="state">
+ {end:}
+ </td>
+ </tr>
+ <tr>
+ <td class="labelcell">
+ Zip
+ </td>
+ <td class="fieldcell">
+ {if:user}
+ <input name="zip" value="{user.getZip()}">
+ {else:}
+ <input name="zip">
+ {end:}
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" align="center">
+ <input type="submit" value="Save">
+ </td>
+ </tr>
+ </table>
+ </form>
+</div>
+<script>
+ $(function(){
+ $('#expire').datepicker();
+ });
+</script>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
+ <title>{title:h}</title>
+ </head>
+ <body>
+ <p>
+ <font size="4" face="arial, sans-serif">
+ <b>{subject:h}</b>
+ </font>
+ </p>
+ <table
+ cellspacing="0"
+ cellpadding="0"
+ bgcolor="#ffffff"
+ border="0"
+ width="400">
+ <tr>
+ <td>
+ {if:approved}
+ <p>Thank you for submitting your request for photos to the Traverse
+ City Convention & Visitors Bureau. Your request has been approved
+ and your login information is below. Please note that your access
+ to this site will be active for 2 weeks, beginning today. Should
+ you require additional time once your access period has expired, we
+ ask that you fill out a new request form.</p>
+ <br>
+ <p>Login: {user.getEmail()}</p>
+ <p>Password: {user.getMediaPass()}</p>
+ <br>
+ <p>Sincerely,</p>
+ <br>
+ <p>The Traverse City Tourism Marketing Team</p>
+ {end:}
+ {if:denied}
+ <p>We're sorry, but your request for media-quality photos did not meet
+ our criteria. However, we encourage you to choose from the wide range
+ of photos available on our general photo library. You do not require
+ a special login to view and download those photos.</p>
+ <br>
+ <p>Thanks for your interest in Traverse City!</p>
+ <p>The Traverse City Tourism Marketing Team</p>
+ {end:}
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <table
+ cellspacing="0"
+ cellpadding="10"
+ border="0"
+ width="400">
+ <tr>
+ <td bgcolor="#eeeeee">
+ <font size="1" face="arial, sans-serif">
+ 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.
+ </font>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ </table>
+ </body>
+ </html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <title>{AppName}</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <link rel="stylesheet" href="main.css">
+ {styles:h}
+ <script>
+ function showMyError(e) {
+ console.log('Error: ' + e.message);
+ console.log('Line: ' + e.lineno);
+ console.log('URL: ' + e.filename);
+ }
+ addEventListener('error', showMyError);
+ </script>
+ {topScripts:h}
+ </head>
+ <body>
+ <header>
+ <hgroup>
+ <h1>{AppName}</h1>
+ </hgroup>
+ <flexy:include src="Admin/nav.html">
+ <flexy:include src="Admin/searchForm.html">
+ </header>
+ {content:h}
+ {bottomScripts:h}
+ </body>
+</html>
--- /dev/null
+<style>
+ .photo-category-list {
+ position: relative;
+ box-shadow: 1px 2px 2px grey;
+ border-radius: 10px;
+ -moz-border-radius: 10px;
+ -webkit-border-radius: 10px;
+ display:block;
+ width: 120px;
+ float: left;
+ background: #D6DFC3;
+ margin: 5px;
+ padding: 10px;
+ height: 140px;
+ }
+ .photo-category-list h1 {
+ position: absolute;
+ bottom: 0;
+ left: 5px;
+ margin: 0;
+ padding: 0;
+ overflow: hidden;
+ width: 123px;
+ }
+ .photo-category-list h1 a {
+ color: #006BB4;
+ font-size: 12px;
+ text-decoration: none;
+ padding: 0;
+ margin: 0;
+ overflow: hidden;
+ white-space: nowrap;
+ }
+ .pCount {
+ text-shadow: 1px 1px grey;
+ position: absolute;
+ top: 0;
+ right: -10px;
+ padding: 1px 5px 1px 5px;
+ background-color: #250;
+ border-radius: 30px;
+ -moz-border-radius: 30px;
+ -webkit-border-radius: 30px;
+ box-shadow: 1px 2px 2px grey;
+ display:inline;
+ float: right;
+ color: white;
+ text-size: 18px;
+ font-weight: bold;
+ }
+ .photo-category-list img {
+ box-shadow: 1px 2px 2px grey;
+ border-radius: 10px;
+ -moz-border-radius: 10px;
+ -webkit-border-radius: 10px;
+ border: none;
+ }
+</style>
+<section>
+ <form id="sortable" method="get">
+ <input type="hidden" name="ac" value="moveCategories">
+ <div
+ class="photo-category-list"
+ flexy:foreach="categories,category">
+ <input type="hidden" name="catPhotos[]" value="{category.getId()}">
+ {if:category.getFirstPhoto()}
+ <a href="{editUrl:h}{category.getId()}">
+ <img width="120" height="120" src="{imgPath:h}{category.getFirstPhoto():h}">
+ </a>
+ {end:}
+ <div class="pCount">
+ {category.getTotalNumberOfPhotos():h}
+ </div>
+ <header>
+ <hgroup>
+ <h1>
+ <a href="{editUrl:h}{category.getId()}">
+ {category.getCategory()}
+ </a>
+ </h1>
+ </hgroup>
+ </header>
+ </div>
+ </form>
+</section>
+<script>
+ $("#sortable").sortable({
+ update: function() {
+ var inputs = $("#sortable").serialize();
+ $.get('./photos.php', inputs, console.log('positions saved'));
+ }
+ });
+</script>
--- /dev/null
+<style>
+ .category-category-list {
+ background: #EFEFEF;
+ border-radius: 5px;
+ display: block;
+ float: left;
+ height: 148px;
+ margin: 0 20px 20px 0;
+ padding: 10px;
+ position: relative;
+ width: 120px;
+ border: 1px solid #CCC;
+ -webkit-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
+ box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
+ }
+ .category-category-list h1 {
+ bottom: 10px;
+ left: 10px;
+ margin: 0;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 123px;
+ }
+ .category-category-list h1 a {
+ color: #006BB4;
+ font-size: 12px;
+ text-decoration: none;
+ padding: 0;
+ margin: 0;
+ overflow: hidden;
+ white-space: nowrap;
+ }
+ .category-category-list img {
+ border: medium none;
+ border-radius: 5px;
+ -webkit-box-shadow: inset 0px 0px 5px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: inset 0px 0px 5px rgba(0, 0, 0, 0.2);
+ box-shadow: inset 0px 0px 5px rgba(0, 0, 0, 0.2);
+ border: 1px solid #CCC;
+ }
+</style>
+<div id="categoryPhotos">
+ <div
+ class="category-category-list"
+ flexy:foreach="photos,photo">
+ {if:photo.getImage()}
+ <a href="{editUrl:h}&catid={photo.getCatid()}&id={photo.getId()}">
+ <img width="120" height="120" src="{imgPath:h}{photo.getImage():h}">
+ </a>
+ {end:}
+ <header>
+ <hgroup>
+ <h1>
+ <a href="{editUrl:h}&catid={photo.getCatid()}&id={photo.getId()}">
+ {photo.getTitle()}
+ </a>
+ </h1>
+ </hgroup>
+ </header>
+ </div>
+</div>
--- /dev/null
+<flexy:include src="Admin/userNav.html">
+<div>
+ <h2>{statusText}</h2>
+ <table id="admin-list-table">
+ <tr>
+ <th width="15">Function</th>
+ <th>Name</th>
+ <th width="50">Expires</th>
+ <th width="10">Approved</th>
+ </tr>
+ <tr flexy:foreach="users,user">
+ <td nowrap="nowrap" align="left">
+ <a href="{editUrl:h}{user.getId()}&userStatus={_REQUEST[userStatus]}">[Edit]</a>
+ </td>
+ <td align="left">{user.getFname()} {user.getLname()}</td>
+ <td align="right">{user.getExpire()}</td>
+ <td align="right">
+ {if:user.getApproved()}
+ Yes
+ {else:}
+ No
+ {end:}
+ </td>
+ </tr>
+ </table>
+</div>
--- /dev/null
+<ul class="admin_nav">
+ <li flexy:if="addCategoryUrl">
+ <a href="{addCategoryUrl}">Add New Category</a>
+ </li>
+ <li flexy:if="addPhotoUrl">
+ <a href="{addPhotoUrl:h}">Add Photo</a>
+ </li>
+ <li flexy:if="addMultipleUrl" id="multiple-link">
+ <a href="{addMultipleUrl:h}">Add Multiple Photos</a>
+ </li>
+ <li flexy:if="listCategoryUrl">
+ <a href="{listCategoryUrl:h}">List Categories</a>
+ </li>
+ <li flexy:if="listUsersUrl">
+ <a href="{listUsersUrl:h}">List Users</a>
+ </li>
+</ul>
--- /dev/null
+<script>
+ $(function() {
+ $("#photoSearch").autocomplete({
+ source: function(request, response) {
+ $.ajax({
+ url: "photos.php?ac=ajaxPhotoSearch",
+ dataType: "json",
+ data: {
+ photoName: request.term
+ },
+ success: function(data) {
+ response(data);
+ }
+ });
+ },
+ minLength: 2
+ });
+ });
+</script>
+<section id="mediaGallerySearchForm">
+ <div id="categorySearchWrapper">
+ <form
+ method="get"
+ action="{categorySearchUrl:h}"
+ id="categoryAdminSearch"
+ name="photoAdminSearch"
+ flexy:ignore="yes">
+ <input type="hidden" name="ac" value="editCategory">
+ <select id="categorySearch" name="id">
+ <option value="">Search By Category</option>
+ <?php
+ if (!empty($t->categories)) {
+ foreach ($t->categories as $category) {
+ echo '<option value="' . $category->getId() . '"';
+ if ($category->getId() == $t->categoryId) {
+ echo ' selected';
+ }
+ echo '>'.$category->getCategory().'</option>';
+ }
+ }
+ ?>
+ </select>
+ <input
+ type="submit"
+ value="Search">
+ </form>
+ <form
+ method="get"
+ action="{photoSearchUrl:h}"
+ id="photoAdminSearch"
+ name="photoAdminSearch"
+ flexy:ignore="yes">
+ <input
+ type="hidden"
+ name="ac"
+ value="searchPhotos">
+ {if:_REQUEST[photoName]}
+ <input
+ type="search"
+ id="photoSearch"
+ name="photoName"
+ value="{_REQUEST[photoName]}"
+ placeholder="Find Photo By Title">
+ {else:}
+ <input
+ type="search"
+ id="photoSearch"
+ name="photoName"
+ placeholder="Find Photo By Title">
+ {end:}
+ <input
+ type="submit"
+ value="Search">
+ </form>
+ </div><!--/#categorySearchWrapper-->
+</section>
--- /dev/null
+<ul class="admin_nav">
+ <li>
+ <a href="{userAdminUrl:h}?ac=listUsers">Pending</a>
+ </li>
+ <li>
+ <a href="{userAdminUrl:h}?ac=listUsers&userStatus=approved">Approved</a>
+ </li>
+ <li>
+ <a href="{userAdminUrl:h}?ac=listUsers&userStatus=denied">Denied</a>
+ </li>
+ <li>
+ <a href="{userAdminUrl:h}?ac=listUsers&userStatus=expired">Expired</a>
+ </li>
+</ul>
--- /dev/null
+<?php
+if ($t->catPhotos) {
+ foreach ($t->catPhotos as $category) {
+ ?>
+ <li>
+ <a
+ href="<?php echo $t->photoUrl;?><?php echo $category->getId();?>">
+ <img
+ title="<?php echo $category->getCategory()?>"
+ src="<?php echo $t->photoUrlSmall.$category->getFirstPhoto()?>">
+ </a>
+ <span class="photoHead"><?php echo $category->getCategory();?></span>
+ </li>
+ <?php
+ }
+}
+?>
\ No newline at end of file
--- /dev/null
+<style>
+#media-photo-gallery {
+ font-size:12px;
+}
+#gallery {
+ clear:both;
+}
+.gallery {
+ text-align: center;
+ list-style: none outside none;
+ padding: 10px 0 0 0;
+}
+.gallery:after {
+ clear: both;
+ content: ".";
+ display: block;
+ height: 0;
+ visibility: hidden;
+}
+.gallery li {
+ background: none repeat scroll 0 0 #F5F3E5;
+ float: left;
+ margin: 0 2% 26px 0;
+ overflow: hidden;
+ position: relative;
+ width: 23%
+}
+/*.gallery li:nth-child(4n+1) {
+ clear: both;
+ margin: 0 16px 26px 0;
+}
+.gallery li:nth-child(4n+2) {
+ margin: 0 16px 26px 0;
+}
+.gallery li:nth-child(4n+3) {
+ margin: 0 16px 26px 0;
+}
+.gallery li:nth-child(4n+4) {
+ margin: 0 0 26px 0;
+}*/
+.gallery li img {
+ width: 100%;
+ border: 1px solid #2797AB;
+ display: block;
+ height: auto;/*width: 143px;*/
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.gallery li:hover img {
+ border: 1px solid #B8C728;
+}
+.gallery .ui-content {
+ overflow: hidden;
+}
+/*#inside #main {
+ width: 720px;
+}*/
+#staticBanners {
+ /*display:none;*/
+}
+.media-gallery-download {
+ font-size: 10px;
+ min-height: 22px;
+}
+#media-photo-gallery div {
+ clear:none;
+ font-size: 1em;
+ height: auto;
+ margin: 0;
+ padding: 0;
+}
+#media-photo-gallery div p {
+ display: block;
+ color: black;
+ padding: 5px;
+ text-shadow: none;
+ font-weight: normal;
+}
+#media-photo-gallery div a {
+}
+#filter_wrapper {
+ overflow: hidden;
+}
+#cat_filter_wrapper {
+ float: left;
+ height: 56px;
+}
+#photoCategoryLabel {
+ float: left;
+}
+#photoCategoryId {
+ float: left;
+ clear: left;
+ width: 180px;
+ height: 24px;
+ border: 1px solid #ABADB3;
+ box-sizing: border-box;
+ padding:.2em;/.3em;
+}
+#photoCategoryId option {
+ padding: 3px;
+}
+#media-login #username {
+ float: left;
+ width: 100px;
+ height: 10px;
+ padding: 5px;
+ margin: 0 5px 0 0;
+ border: 1px solid #ABADB3;
+}
+#media-login #password {
+ float: left;
+ width: 100px;
+ height: 10px;
+ padding: 5px;
+ margin: 0 5px 0 0;
+ border: 1px solid #ABADB3;
+}
+#media-login #submit {
+ display: block;
+ float: left;
+ width: 24px;
+ height: 22px;
+ cursor: pointer;
+ background: url(<?php echo $t->base_url;?>assets/play.gif) 50% 50% no-repeat;
+ border: 1px solid #ABADB3;
+ -bracket-:hack(;
+ height: 22px;
+ );
+}
+.photoHead {
+ display: block;
+ text-align: center;
+ min-height: 38px;
+ margin: 0 !important;
+ padding: 5px;
+ background: none;
+}
+.captionWrapper {
+ display: block;
+ width: 100%;
+ overflow: hidden;
+}
+.captionTitleWrapper {
+ display: block;
+ width: 50%;
+ float: left;
+ font-size: 18px;
+ font-size: 1.8rem;
+ font-weight: bold;
+ color: #FFF;
+ text-align: left;
+ padding: 10px 20px;
+ margin: 0;
+}
+.captionDescWrapper {
+ display: block;
+ width: 50%;
+ float: left;
+ clear: left;
+ font-size: 14px;
+ font-size: 1.4rem;
+ color: #FFF;
+ text-align: left;
+ padding: 0 20px 10px 20px;
+ margin: 0;
+}
+.download_wrapper {
+ display: block;
+ position: absolute;
+ z-index: 99;
+ top: 10px;
+ right: 20px;
+ width: 30%;
+ font-size: 14px;
+ font-size: 1.4rem;
+ color: #FFF;
+ text-align: left;
+ padding: 6px 0 10px 20px;
+ margin: 0;
+ text-align: right;
+}
+.download_wrapper a {
+ color: #CCC;
+}
+.download_wrapper a:hover {
+ color: #FFF;
+}
+.ps-caption-content {
+ width: 100%;
+ overflow: hidden;
+ position: relative;
+}
+</style>
+<flexy:toJavascript flexy:prefix="" base_url="base_url" ></flexy:toJavascript>
+<flexy:toJavascript flexy:prefix="" pageId="pageId" ></flexy:toJavascript>
+<div id="media-photo-gallery">
+ <div id="filter_wrapper">
+ <div id="cat_filter_wrapper">
+ <div class="name_wrapper" flexy:if="photoNameSearch">
+ <h2>Filter By Name</h2>
+ <form
+ method="get"
+ id="photoGallery"
+ action="{photoSearchFormUrl:h}"
+ flexy:ignore="yes">
+ <input type="hidden" name="catid" value="{_REQUEST[catid]}">
+ <label id="photoNameLabel"></label>
+ <input
+ type="search"
+ name="photo_name"
+ id="photoSearch"
+ value="{_REQUEST[photo_name]}"
+ placeholder="Name">
+ <input type="submit" value="Search">
+ </form>
+ </div>
+ <?php if (count($t->categories) > 1) {?>
+ <div class="cat_wrapper">
+ <h2>Filter By Category</h2>
+ <form
+ method="get"
+ id="photoGallery"
+ action="{photoSearchFormUrl:h}"
+ flexy:ignore="yes">
+ <input type="hidden" name="catid" value="{_REQUEST[catid]}">
+ <label id="photoCategoryLabel"></label><!--/Filter By Category-->
+ <select id="photoCategoryId" name="photoCategoryId">
+ <option value="">Show Categories</option>
+ <?php foreach ($t->categories as $category) {
+ echo '<option value="'.$category['id'].'"';
+ if ($_REQUEST['photoCategoryId'] == $category['id']) {
+ echo ' selected';
+ }
+ echo '>'.$category['category'].'</option>';
+ }?>
+ </select>
+ </form>
+ </div>
+ <?php }?>
+
+ </div><!--/#cat_filter_wrapper-->
+ <div style="float:right;" flexy:if="mediaExclusive">
+ {if:isLoggedIn}
+ You're logged in! <a href="{logoutUrl:h}">Logout</a>
+ {else:}
+ <label>Media Login</label>
+ <form
+ id="media-login"
+ method="post"
+ action="{loginUrl:h}"
+ flexy:ignore="yes">
+ <input
+ type="hidden"
+ name="catid"
+ value="{_REQUEST[catid]}">
+ <input
+ id="username"
+ name="username"
+ placeholder="Username"
+ size="10"
+ required>
+ <input
+ id="password"
+ type="password"
+ name="password"
+ placeholder="Password"
+ size="10"
+ required>
+ <input
+ id="submit"
+ type="submit"
+ value="">
+ </form>
+ {if:failedStatus}
+ <div style="clear:both;width:250px;color:red;text-wrap: normal;">
+ {failedStatus:h}
+ </div>
+ {end:}
+ {end:}
+ </div>
+ </div>
+ <div class="gallery_wrapper">
+ <div flexy:if="expired">
+ <p>We’re sorry, but your access to this page has expired. If you
+ require additional time to select photos, please fill out and
+ submit a new
+ <a href="{mediaGalleryRequestFormUrl:h}">photo request form</a>.
+ If approved, you will receive your new login information by email
+ within 1 to 2 days.</p>
+
+ <p>Sincerely,</p>
+
+ <p>The Traverse City Tourism Marketing Team</p>
+ </div>
+ <h2 flexy:if="photoCategoryName">{photoCategoryName}</h2>
+ <ul id="Gallery" class="gallery">
+ {if:photos}
+ <flexy:include src="photos.html">
+ {end:}
+ {if:catPhotos}
+ <flexy:include src="photoCats.html">
+ {end:}
+ </ul>
+ {if:mediaExclusive}
+ <div flexy:if="!isLoggedIn">
+ <p>Are you a member of the media and looking for additional or
+ specific photos?
+ <a href="{mediaGalleryRequestFormUrl:h}">Click Here</a>.</p>
+ </div>
+ {end:}
+ </div>
+</div>
+{if:photoNameSearch}
+<script>
+ $(function() {
+ $("#photoSearch").autocomplete({
+ source: function(request, response) {
+ $.ajax({
+ url: "photoSearch",
+ dataType: "json",
+ data: {
+ photoName: request.term,
+ pageId: pageId
+ },
+ success: function(data) {
+ response(data);
+ }
+ });
+ },
+ minLength: 2
+ });
+ });
+</script>
+{end:}
\ No newline at end of file
--- /dev/null
+<?php
+if ($t->photos) {
+ foreach ($t->photos as $photo) {
+ ?>
+ <li>
+ <a data-download="<?php if($photo->getDownload()){echo '1';}else{echo '0';}?>" data-photoid="<?php echo $photo->getId()?>" data-download="<?php echo $photo->getDownload()?>" rel="<?php echo htmlspecialchars($photo->getDescription())?>" title="<?php echo htmlspecialchars($photo->getTitle())?>" class="photoimg" href="<?php echo $t->photoUrlLarge.$photo->getImage()?>">
+ <img title="<?php echo htmlspecialchars($photo->getTitle())?>" alt="<?php echo htmlspecialchars($photo->getDescription())?>" src="<?php echo $t->photoUrlSmall.$photo->getImage()?>">
+ <?php if ($photo->getTitle()) {?>
+ <span class="photoHead">
+ <?php
+ $tempTitle = $photo->getTitle();
+ if(strlen($tempTitle) > 50) {
+ $tempTitle = substr($tempTitle, 0, 47);
+ $tempTitle .= "...";
+ }
+ echo $tempTitle;
+ //echo $photo->getTitle();
+ ?>
+ </span>
+ <?php } ?>
+ </a>
+ <?php if ($photo->getDownload()) {?>
+ <span class="media-gallery-download">
+ Download for
+ <a href="<?php echo $t->photoDownWeb.$photo->getId()?>/">Web</a> - <a href="<?php echo $t->photoDownPrint.$photo->getId()?>/">Print</a>
+ </span>
+ <?php } ?>
+ </li>
+ <?php }
+}
+?>
--- /dev/null
+<?php
+
+/**
+ * AdminEditVideoForm.php
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Toolkit_Videos_AdminEditVideoForm
+ *
+ * Handles the form generation and processing of the Video Edit Page
+ *
+ * @category Toolkit
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2008 Gaslight media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Videos_AdminEditVideoForm
+ extends Toolkit_FormBuilder
+{
+ /**
+ * What do you want the success msg to be if the form validates successfully
+ *
+ * @var string
+ * @access protected
+ */
+ protected $successMsg
+ = '<div id="form-success-top">Coupon successfully updated.</div>';
+
+ /**
+ * 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.
+ *
+ * @var string
+ * @access protected
+ */
+ protected $registeredRules = array(
+ array(
+ 'checkURI',
+ 'callback',
+ 'uri',
+ 'Validate'
+ )
+ );
+ public $errorMsg = '
+ <div id="form-warning-top">There was a Problem with your form!</div>';
+
+ /**
+ * Setup Form Constants
+ *
+ * Constants are form values (hidden) fields most likely that cannot be
+ * changed by user input
+ *
+ * @return void
+ */
+ public function configureConstants()
+ {
+ $c = array();
+ $this->setConstants($c);
+ }
+
+ /**
+ * Setup Form Defaults
+ *
+ * if $_GET['id'] is numeric then it creates a Toolkit_Videos_Video
+ * class object and gets set as form element defaults
+ *
+ * @param PDO $dbh Database Connection
+ *
+ * @return void
+ */
+ public function configureDefaults(PDO $dbh)
+ {
+ $d = array();
+ if (is_numeric($_GET['id'])) {
+ $video = new Toolkit_Videos_VideoMapper($dbh);
+ $d = $video->getVideoById($_GET['id']);
+ }
+ $this->setDefaults($d);
+ }
+
+ /**
+ * Setup the Form elements
+ *
+ * @param PDO $dbh Database Connection
+ * @param Config_Container $c PEAR::Config_Container object
+ *
+ * @return void
+ */
+ public function configureElements(PDO $dbh, Config_Container $c)
+ {
+ $e = array();
+
+ // get reference to [conf] section of config file
+ $appHasFeaturedVideos
+ = $c->getItem('section', 'conf')
+ ->getItem('directive', 'featuredVideos')
+ ->getContent();
+ // All Elements are created here.
+ // This includes group element definitions.
+ $e[] = array(
+ 'type' => 'advcheckbox',
+ 'req' => false,
+ 'name' => 'active',
+ 'display' => 'Active',
+ 'val' => array(0, 1)
+ );
+ if ($appHasFeaturedVideos) {
+ $e[] = array(
+ 'type' => 'advcheckbox',
+ 'req' => false,
+ 'name' => 'featured',
+ 'display' => 'Featured',
+ 'val' => array(0, 1)
+ );
+ } else {
+ $e[] = array(
+ 'type' => 'hidden',
+ 'req' => false,
+ 'name' => 'featured'
+ );
+ }
+ $e[] = array(
+ 'type' => 'text',
+ 'req' => true,
+ 'name' => 'video_url',
+ 'display' => 'Video Link<br>
+ <span style="color:blue">
+ Click on the \'Share\' function on the YouTube video
+ <br>to get your link. If you\'re having problems click on "show options"
+ and select "long link"</span>',
+ 'opts' => array('class' => 'text','size'=>50)
+ );
+ $e[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'submit_rmv',
+ 'display' => 'Submit Video',
+ 'opts' => array('id' => 'submit')
+ );
+ if (ctype_digit($_GET['id'])) {
+ $e[] = array(
+ 'type' => 'submit',
+ 'req' => false,
+ 'name' => 'delete_rmv',
+ 'display' => 'Delete Video',
+ 'opts' => array('id' => 'delete')
+ );
+ }
+
+ $this->setupElements($e);
+ }
+
+ /**
+ * Setup Form filters
+ *
+ * @return void
+ */
+ public function configureFilters()
+ {
+ $f = array();
+ $f[] = array(
+ 'element' => '__ALL__',
+ 'filter' => 'trim'
+ );
+ $f[] = array(
+ 'element' => 'url',
+ 'filter' => array('Toolkit_Common', 'filterURI')
+ );
+
+ $this->setupFilters($f);
+ }
+
+ /**
+ * Runs all function to setup the Form
+ *
+ * @param PDO $dbh Database Connection
+ * @param Config_Container $c PEAR::Config_Container object
+ *
+ * @return void
+ */
+ public function configureForm(
+ PDO $dbh,
+ Config_Container $c
+ ) {
+ $this->configureElements($dbh, $c);
+ $this->configureFilters();
+ $this->configureRules();
+ $this->configureDefaults($dbh);
+ $this->configureConstants();
+ }
+
+ /**
+ * Setup the Form's rules
+ *
+ * @return void
+ */
+ public function configureRules()
+ {
+ $r = array();
+
+ $r[] = array(
+ 'element' => 'video_url',
+ 'message' => 'ERROR: Invalid URL format (http)',
+ 'type' => 'checkURI',
+ 'format' => array(
+ 'allowed_schemes' => array('http'),
+ 'strict' => false
+ ),
+ 'validation' => $this->validationType,
+ 'reset' => false,
+ 'force' => false
+ );
+
+
+ $this->setupRules($r);
+ }
+
+ /**
+ * _processData function creates an video object Toolkit_Videos_Video
+ * if id exists it creates the object by id
+ * else it creates a new object
+ * saved is called and the object is either created or updated
+ *
+ * If the $values['id'] is given it creates a Toolkit_Videos_VideoMapper
+ * object and get the video object using the getVideoById method
+ * If not it then just creates an empty video object
+ * The object is then updated using it's accessor method and saved
+ *
+ * @param type $dbh Database Connection
+ * @param type $values Form $values
+ *
+ * @return void
+ */
+ private function _processData($dbh, $values)
+ {
+ $videoMapper = new Toolkit_Videos_VideoMapper($dbh);
+ if ($_GET['id']) {
+ $video = $videoMapper->getVideoById($_GET['id'], false);
+ } else {
+ $video = new Toolkit_Videos_Video();
+ }
+ $video->setVideo_url($values['video_url'])
+ ->setFeatured($values['featured'])
+ ->setActive($values['active']);
+
+ $video->save($dbh);
+ }
+
+ /**
+ * Output HTML for the form
+ *
+ * @param PDO $dbh Database Connection
+ *
+ * @return string|boolean
+ */
+ public function toHtml(PDO $dbh)
+ {
+ // Handle Deleting banner.
+ if ( $this->isSubmitted()
+ && ctype_digit($_GET['id'])
+ ) {
+ if ($this->getSubmitValue('delete_rmv')) {
+ $videoMapper = new Toolkit_Videos_VideoMapper($dbh);
+ $video = $videoMapper->getVideoById($_GET['id'], false);
+ if ($video instanceof Toolkit_Videos_Video) {
+ if ($video->delete($dbh, $is)) {
+ return 'Video successfully deleted.';
+ }
+ } else {
+ // the coupon has already been deleted or doesn't exist.
+ return "The video has already been deleted or doesn't exists.";
+ }
+ header ('Location: videos.php');
+ return false;
+ }
+ }
+
+ $this->setupRenderers();
+ if ($this->validate()) {
+ $this->cleanForm();
+
+ $submitValues = $this->getSubmitValues();
+ if ($this->_processData($dbh, $submitValues)) {
+ $this->freeze();
+ $output = $this->successMsg;
+ }
+ header('Location: videos.php');
+ } elseif ($this->isSubmitted()) {
+ $output = $this->errorMsg;
+ $output .= parent::toHTML();
+ } else {
+ $output = parent::toHTML();
+ }
+ return $output;
+ }
+
+}
--- /dev/null
+<?php
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/**
+ * Description of Controller
+ *
+ * @author steve
+ */
+class Toolkit_Videos_Controller {
+
+ protected $flexyOptions;
+
+ public function getFlexyOptions()
+ {
+ return $this->flexyOptions;
+ }
+
+ public function setFlexyOptions($flexyOptions)
+ {
+ $this->flexyOptions = $flexyOptions;
+ }
+
+ function __construct()
+ {
+ $options = $GLOBALS['flexyOptions'];
+ $options['templateDir']
+ = dirname(__FILE__) . '/templates';
+ $options['compileDir']
+ = dirname(__FILE__) . '/templates/compiled';
+ $this->flexyOptions = $options;
+ }
+
+ public function toHtml(PDO $dbh, Config_Container $appConf)
+ {
+ switch ($_GET['module']) {
+ case 'editVideo':
+ $form = new Toolkit_Videos_AdminEditVideoForm(
+ 'edit-video'
+ );
+ $form->configureForm($dbh, $appConf);
+ $ret = $form->toHtml($dbh);
+ break;
+ case 'listVideo':
+ default:
+ $videos = new Toolkit_Videos_VideosDataGrid($dbh);
+ $videos->setConfig($appConf);
+ $videos->setQuery();
+ $videos->setDefaultSort(array('pos' => 'ASC'));
+ $ret .= $videos->toHtml($appConf);
+ break;
+ }
+ return $ret;
+ }
+}
+?>
--- /dev/null
+--
+-- setup schema
+--
+
+CREATE SCHEMA videos;
+GRANT ALL ON SCHEMA videos TO nobody;
+
+--
+-- Tables
+--
+
+\i ./table/videos.sql
--- /dev/null
+--
+-- Drops schema
+-- WARNING: CANNOT BE UNDONE
+--
+
+DROP SCHEMA IF EXISTS videos CASCADE;
\ No newline at end of file
--- /dev/null
+CREATE TABLE videos.videos (
+ id SERIAL,
+ create_date DATE DEFAULT current_date,
+ video_url TEXT,
+ active BOOLEAN,
+ featured BOOLEAN,
+ pos INT DEFAULT 1,
+ PRIMARY KEY (id)
+);
+
+GRANT ALL ON videos.videos TO nobody;
+GRANT ALL ON videos.videos_id_seq TO nobody;
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * IDecorator.php
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Toolkit_Videos_IDecorator
+ *
+ * Inteface class for the Toolkit_Videos_Decorators
+ * In future there may be more decorators here we're insurring that they have
+ * simular API's
+ *
+ * @category Toolkit
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2008 Gaslight media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+interface Toolkit_Videos_IDecorator
+{
+ /**
+ * Class Constructor
+ *
+ * @return void
+ */
+ public function __construct();
+
+ /**
+ * Handles setting up the PEAR::HTML_Template_Flexy options
+ *
+ * @return void
+ */
+ public function setFlexyOptions();
+ /**
+ * Handles creating HTML output
+ *
+ * @param PDO $dbh Database Connection
+ * @param object $gateway Gateway Object
+ *
+ * @return string
+ */
+ public function toHtml(
+ PDO $dbh,
+ $gateway = null
+ );
+}
--- /dev/null
+<?php
+
+/**
+ * Navigation.php
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Toolkit_Videos_Navigation
+ *
+ * Handles the navigation for the Video admin side
+ *
+ * @category Toolkit
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2008 Gaslight media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Videos_Navigation
+ extends Toolkit_NavigationAbstract
+ implements Toolkit_INavigation
+{
+ // {{{ __construct()
+
+ /**
+ * Class Constructor
+ *
+ * @param HTML_Menu $menu Menu to use
+ * @param HTML_Menu_Renderer $rEngine Render to use
+ *
+ * @return void
+ */
+ public function __construct(
+ HTML_Menu $menu,
+ HTML_Menu_Renderer $rEngine
+ ) {
+ $this->menu = $menu;
+ $this->rEngine = $rEngine;
+ $this->currIndex = 'listCoupons';
+ }
+
+ /**
+ * Create templates for the navigation
+ *
+ * @return void
+ */
+ protected function setNavTemplates()
+ {
+ $tpl = '<li><a href="%s" title="%s">{Title}</a></li>';
+ $this->rEngine->setEntryTemplate(
+ HTML_MENU_ENTRY_INACTIVE,
+ sprintf($tpl, '{url}', '{desc}', '{Title}')
+ );
+ $this->rEngine->setEntryTemplate(
+ HTML_MENU_ENTRY_ACTIVE,
+ sprintf($tpl, '{url}', '{desc}', '{Title}')
+ );
+ $this->rEngine->setEntryTemplate(
+ HTML_MENU_ENTRY_ACTIVEPATH,
+ sprintf($tpl, '{url}', '{desc}', '{Title}')
+ );
+ $this->rEngine->setMenuTemplate('', '');
+ $this->rEngine->setRowTemplate('<ul class="admin_nav">', '</ul>');
+ }
+
+ /**
+ * force the current index to $_GET['page']
+ *
+ * @return void
+ */
+ protected function setCurrentIndex()
+ {
+ $this->menu->forceCurrentIndex($_GET['page']);
+ }
+
+ // }}}
+ // {{{ getNavSructure()
+ // @codeCoverageIgnoreStart
+
+ /**
+ * Sets up a multi dimensional array used for the nav structure
+ *
+ * @param Config_Container $c Application configuration
+ *
+ * @return array navigational array hash
+ * @access public
+ */
+ public function getNavStructure(Config_Container $c)
+ {
+ // get reference to [listing type] section of config file
+ $singularType = $c->getItem('section', 'listing type')
+ ->getItem('directive', 'singular')
+ ->getContent();
+ $pluralType = $c->getItem('section', 'listing type')
+ ->getItem('directive', 'plural')
+ ->getContent();
+
+ $nav = array(
+ 'listVideos' => array(
+ 'Title' => "List {$pluralType}",
+ 'url' => MEDIA_BASE_URL . 'admin/videos.php?page=listVideos&module=listVideos',
+ 'desc' => "Display all the {$pluralType}",
+ ),
+ 'editVideo' => array(
+ 'Title' => "Add {$singularType}",
+ 'url' => MEDIA_BASE_URL . 'admin/videos.php?page=editVideo&module=editVideo',
+ 'desc' => "Edit a {$singularType}"
+ ),
+ );
+
+ return $nav;
+ }
+
+ // @codeCoverageIgnoreEnd
+}
--- /dev/null
+<?php
+
+/**
+ * Video.php
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Toolkit_Videos_Video
+ *
+ * Object Data pattern class for the Video PDO Table
+ *
+ * @category Toolkit
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2008 Gaslight media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Videos_Video
+{
+
+ protected $id;
+ protected $video_url;
+ protected $pos;
+ protected $featured;
+ protected $active;
+
+ /**
+ * Handles the work of Inserting a video record into the database
+ * returns the id for the new record
+ *
+ * @param PDO $dbh Database Connection
+ *
+ * @return int
+ */
+ private function _insert(PDO $dbh)
+ {
+ $classData = $this->getClassAsArray();
+ unset($classData['id']);
+ $pos = $this->getMaxPos();
+ $classData['pos'] = ++$pos;
+ $sql = Toolkit_Common::createSQLInsert(
+ 'videos',
+ array_keys($classData)
+ );
+ $sql .= " RETURNING id";
+ $stmt = Toolkit_Common::prepareQuery(
+ $dbh,
+ 'videos',
+ $sql,
+ $classData
+ );
+ $stmt->execute();
+ return $stmt->fetchColumn();
+ }
+
+ /**
+ * Handles the update of the record on the database record
+ *
+ * @param PDO $dbh Database Connection
+ *
+ * @return int
+ */
+ private function _update(PDO $dbh)
+ {
+ $classData = $this->getClassAsArray();
+ $sql = Toolkit_Common::createSQLUpdate(
+ 'videos',
+ array_keys($classData),
+ array('id = :id')
+ );
+ return Toolkit_Common::processQuery(
+ $dbh,
+ 'videos',
+ $sql,
+ $classData
+ );
+ }
+
+ /**
+ * Handles the deletion of the record in the database and reordering
+ * any other videos in the table
+ *
+ * @param PDO $dbh Database Connection
+ *
+ * @return void
+ */
+ public function delete(PDO $dbh)
+ {
+ try {
+ $dbh->beginTransaction();
+ $sql = "
+ DELETE
+ FROM videos
+ WHERE id = :id";
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(
+ ':id',
+ $this->getId(),
+ PDO::PARAM_INT
+ );
+ $stmt->execute();
+ // we have to reorder the positions for the rest of the videos
+ $sql = "
+ UPDATE videos
+ SET pos = pos - 1
+ WHERE pos >= :oldpos";
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(':oldpos', $this->getPos(), PDO::PARAM_INT);
+ $stmt->execute();
+ $dbh->commit();
+ } catch(PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+ /**
+ * active getter
+ *
+ * @return boolean
+ */
+ public function getActive()
+ {
+ return $this->active;
+ }
+
+ /**
+ * active setter the given values is cast to a boolean value
+ * so if you send in a string 'true' or 'false' both will be cast to true
+ *
+ * @param boolean $active Active flag
+ *
+ * @return Toolkit_Videos_Video
+ */
+ public function setActive($active)
+ {
+ $this->active = (bool)$active;
+ return $this;
+ }
+
+ /**
+ * id getter
+ *
+ * @return int
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * id setter
+ *
+ * @param int $id integer for the record id
+ *
+ * @return Toolkit_Videos_Video
+ */
+ public function setId($id)
+ {
+ if (!$this->id) {
+ $this->id = $id;
+ }
+ return $this;
+ }
+
+ /**
+ * video_url getter
+ *
+ * @return string
+ */
+ public function getVideo_url()
+ {
+ return $this->video_url;
+ }
+
+ /**
+ * video_url settur
+ *
+ * @param string $video_url the youtube video url
+ *
+ * @return Toolkit_Videos_Video
+ */
+ public function setVideo_url($video_url)
+ {
+ $this->video_url = $video_url;
+ return $this;
+ }
+
+ /**
+ * pos getter
+ *
+ * @return int
+ */
+ public function getPos()
+ {
+ return $this->pos;
+ }
+
+ /**
+ * pos setter
+ *
+ * @param type $pos Position number for the video
+ *
+ * @return Toolkit_Videos_Video
+ */
+ public function setPos($pos)
+ {
+ $this->pos = $pos;
+ return $this;
+ }
+
+ /**
+ * featured getter
+ *
+ * @return boolean
+ */
+ public function getFeatured()
+ {
+ return $this->featured;
+ }
+
+ /**
+ * featured setter needs to be boolean not a string
+ *
+ * @param boolean $featured Featured flag
+ *
+ * @return Toolkit_Videos_Video
+ */
+ public function setFeatured($featured)
+ {
+ $this->featured = (bool)$featured;
+ return $this;
+ }
+
+ /**
+ * Handles the saving of the object to the database
+ *
+ * If the object has an id field set then update the record or else
+ * create a new one
+ *
+ * @param PDO $dbh Database Connection
+ *
+ * @return void
+ */
+ public function save(PDO $dbh)
+ {
+ if ($this->getId()) {
+ $this->_update($dbh);
+ } else {
+ $this->_insert($dbh);
+ }
+ }
+
+ /**
+ * Create an array of the class fields
+ *
+ * @return array
+ */
+ public function getClassAsArray()
+ {
+ $data = array();
+ $classData = get_class_vars(get_class($this));
+ foreach ($classData as $fieldName => $element) {
+ $getFunc = 'get' . ucfirst($fieldName);
+ $data[$fieldName] = $this->$getFunc();
+ }
+ return $data;
+ }
+
+ /**
+ * Get the max position for the videos
+ *
+ * @staticvar int $maxPos position of the video
+ * @return int
+ */
+ public function getMaxPos()
+ {
+ static $maxPos;
+ if (!$maxPos) {
+ $dbh = Toolkit_Database::getInstance();
+ $sql = "
+ SELECT count(id) as maxpos
+ FROM videos";
+ $ret = $dbh->query($sql);
+ $maxPos = $ret->fetchColumn();
+ }
+ return (int)$maxPos;
+ }
+
+ /**
+ * Create the youtube url
+ *
+ * Using preg_match on two pattern to return the video url portion
+ * first is /v=(.*)$/ older style
+ * second is /youtu.be\/(.*)/
+ * These may need to be updated if youtube creates newer embed codes
+ *
+ * @return boolean
+ */
+ public function getVideoCode()
+ {
+ $pattern = '/v=(.*)$/';
+ $pattern2 = '/youtu.be\/(.*)/';
+ $vidUrl = $this->getVideo_url();
+ if (preg_match($pattern, $vidUrl, $match)) {
+ return $match[1];
+ } else if (preg_match($pattern2, $vidUrl, $match)) {
+ return $match[1];
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Using the youtube API get the video title for the embed url
+ *
+ * @return string
+ */
+ public function getVideoTitle()
+ {
+ $url = "http://gdata.youtube.com/feeds/api/videos/". $this->getVideoCode();
+ $ch = curl_init();
+ $curlOptions = array(
+ CURLOPT_URL => $url,
+ CURLOPT_HEADER => 0,
+ CURLOPT_RETURNTRANSFER => 1
+ );
+ curl_setopt_array($ch, $curlOptions);
+
+ $response = curl_exec($ch);
+ curl_close($ch);
+ $doc = new DOMDocument;
+ $doc->loadXML($response);
+ $title = $doc->getElementsByTagName("title")->item(0)->nodeValue;
+ return $title;
+ }
+
+}
--- /dev/null
+<?php
+
+/**
+ * Video.php
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Toolkit_Videos_Video
+ *
+ * Object Mapper pattern class for the Video PDO Table. Creates
+ * Toolkit_Video_Video objects by values or by id
+ *
+ * @category Toolkit
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2008 Gaslight media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Videos_VideoMapper
+{
+
+ /**
+ * Class Constructor
+ *
+ * @param PDO $pdo Database Connection
+ */
+ function __construct(PDO $pdo)
+ {
+ $this->dbh = $pdo;
+ }
+
+ /**
+ * Creates Video object by a given array of values
+ * values must be set with the Videos fields as keys
+ *
+ * @param array $values array of values
+ *
+ * @return Toolkit_Videos_Video
+ */
+ public function createByValues($values)
+ {
+ $video = new Toolkit_Videos_Video();
+ $video->setId($values['id'])
+ ->setVideo_url($values['video_url'])
+ ->setActive($values['active'])
+ ->setfeatured($values['featured'])
+ ->setPos($this->getMaxPos());
+ return $video;
+ }
+
+ public function getMaxPos()
+ {
+ $dbh = Toolkit_Database::getInstance();
+ $sql = "
+ SELECT count(id) as maxpos
+ FROM videos";
+ $ret = $dbh->query($sql);
+ $maxPos = $ret->fetchColumn();
+ if ((int) $maxPos == 0) {
+ $maxPos = 1;
+ }
+ return $maxPos;
+ }
+ /**
+ * Create Video object by a given id
+ * if the id is not found then it does not return
+ *
+ * @param int $id id for the video record
+ * @param array $returnArray Can return the array instead of object
+ *
+ * @return mixed
+ */
+ public function getVideoById($id, $returnArray = true)
+ {
+ try {
+ $sql = "
+ SELECT *
+ FROM videos
+ WHERE id = :id";
+ $stmt = $this->dbh->prepare($sql);
+ $stmt->bindParam(
+ ':id', $id, PDO::PARAM_INT
+ );
+ $stmt->execute();
+ $res = $stmt->fetch(PDO::FETCH_ASSOC);
+ if ($res) {
+ $video = new Toolkit_Videos_Video();
+ $video->setId($res['id'])
+ ->setVideo_url($res['video_url'])
+ ->setActive($res['active'])
+ ->setfeatured($res['featured'])
+ ->setPos($res['pos']);
+ return ($returnArray)
+ ? $video->getClassAsArray()
+ : $video;
+ }
+ } catch(PDOException $e) {
+ Toolkit_Common::handleError($e);
+ }
+ }
+
+}
--- /dev/null
+<?php
+
+/**
+ * VideosDataGrid.php
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Toolkit_Videos_VideosDataGrid
+ *
+ * Handles the listing of the videos using the PEAR::Structures_DataGrid
+ * extended from our class Toolkit_DataGridBuilder
+ *
+ * @category Toolkit
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2008 Gaslight media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Videos_VideosDataGrid
+ extends Toolkit_DataGridBuilder
+{
+
+ /**
+ * Description for protected
+ * @var string
+ * @access protected
+ */
+ protected $noRecMessage = 'No Videos Found.';
+
+ protected $config;
+
+ /**
+ * Set the config
+ *
+ * @param Config_Container $config
+ */
+ public function setConfig(Config_Container $config)
+ {
+ $this->config = $config;
+ }
+
+ /**
+ * Configure the columns for the datagrid
+ *
+ * @param Config_Container $c PEAR::Config_Container object
+ *
+ * @return void
+ * @access protected
+ */
+ protected function configureColumns()
+ {
+ // get reference to [conf] section of config file
+ $appHasFeaturedVideos
+ = $this->config->getItem('section', 'conf')
+ ->getItem('directive', 'featuredVideos')
+ ->getContent();
+
+ $this->addColumn(
+ new Structures_DataGrid_Column(
+ 'Function',
+ null,
+ null,
+ array('class' => 'editLink'),
+ null,
+ array(&$this, 'renderEditLink')
+ )
+ );
+
+ $this->addColumn(
+ new Structures_DataGrid_Column(
+ 'Active',
+ null,
+ null,
+ null,
+ null,
+ array($this, 'renderActive')
+ )
+ );
+
+ if ($appHasFeaturedVideos) {
+ $this->addColumn(
+ new Structures_DataGrid_Column(
+ 'Featured',
+ null,
+ null,
+ null,
+ null,
+ array($this, 'renderFeatured')
+ )
+ );
+ }
+
+ $this->addColumn(
+ new Structures_DataGrid_Column(
+ 'Position',
+ null,
+ null,
+ null,
+ null,
+ array($this, 'renderPos')
+ )
+ );
+
+ $this->addColumn(
+ new Structures_DataGrid_Column(
+ 'Video Url',
+ 'video_url',
+ null
+ )
+ );
+
+ $this->addColumn(
+ new Structures_DataGrid_Column(
+ 'Thumbnail',
+ null,
+ null,
+ null,
+ null,
+ array($this, 'renderThumbNail')
+ )
+ );
+ }
+
+ /**
+ * Get the max position for the videos for generating a drop down for
+ * reordering them in the datagrid
+ *
+ * @staticvar type $maxPos
+ * @return int
+ */
+ public function getMaxPos()
+ {
+ static $maxPos;
+ if (!$maxPos) {
+ $dbh = Toolkit_Database::getInstance();
+ $sql = "
+ SELECT count(id) as maxpos
+ FROM videos";
+ $ret = $dbh->query($sql);
+ $row = $ret->fetch(PDO::FETCH_ASSOC);
+ if ((int)$row['maxpos'] == 0) {
+ $maxPos = 1;
+ } else {
+ $maxPos = $row['maxpos'];
+ }
+ }
+ return (int)$maxPos;
+ }
+
+ /**
+ * Render the edit link for a category
+ *
+ * @param array $data DB record
+ *
+ * @return mixed Link to edit a category
+ * @access public
+ */
+ public function renderEditLink($data)
+ {
+ extract($data['record']);
+ $link = '<a href="%sadmin/videos.php?page=editVideo&module=editVideo&id=%s">Edit</a>';
+ return sprintf($link, MEDIA_BASE_URL, $id);
+ }
+
+ /**
+ * Handles rendering the pos column
+ *
+ * @param type $data Data array
+ *
+ * @return string
+ */
+ public function renderPos($data)
+ {
+ extract($data['record']);
+ $html = '<select name="position" rel="'.$id.'" class="posSelect">';
+ $maxPos = $this->getMaxPos();
+ for ($i = 1; $i <= $maxPos; ++$i) {
+ $html .= '<option value="'.$i.'"';
+ if ($pos == $i) {
+ $html .= ' selected="selected"';
+ }
+ $html .= '>'.$i.'</option>';
+ }
+ $html .= '</select>';
+ return $html;
+ }
+
+ /**
+ * Handles rendering the thumbnail column
+ *
+ * @param type $data Data array
+ *
+ * @return string
+ */
+ public function renderThumbNail($data)
+ {
+ extract($data['record']);
+ $pattern = '/v=(.*)/';
+ $pattern2 = '/youtu.be\/(.*)/';
+ if (preg_match($pattern, $video_url, $match)) {
+ $vidCode = $match[1];
+ } else if (preg_match($pattern2, $video_url, $match)) {
+ $vidCode = $match[1];
+ }
+ $thumb = ($vidCode)
+ ? '<a href="http://www.youtube.com/embed/'.$vidCode.'?rel=0" class="colorbox"><img src="http://img.youtube.com/vi/'.$vidCode.'/default.jpg"></a>'
+ : '';
+ return $thumb;
+ }
+
+ /**
+ * Handles rendering the active column
+ *
+ * @param type $data Data array
+ *
+ * @return string
+ */
+ public function renderActive($data)
+ {
+ $active = $data['record']['active'];
+ $link = MEDIA_BASE_URL . 'video-active-toggle/'.$data['record']['id'].'/';
+ $ball
+ = ($active)
+ ? 'grnball.gif'
+ : 'redball.gif';
+ $html = sprintf(
+ '<a href="%s"><img border="0" src="%sToolkit/Toolbox/assets/%s"></a>',
+ $link,
+ MEDIA_BASE_URL,
+ $ball
+ );
+ return $html;
+ }
+
+ /**
+ * Handles rendering the featured column
+ *
+ * @param type $data Data array
+ *
+ * @return type
+ */
+ public function renderFeatured($data)
+ {
+ $featured = $data['record']['featured'];
+ $link = MEDIA_BASE_URL . 'video-featured-toggle/'.$data['record']['id'].'/';
+ $ball
+ = ($featured)
+ ? 'grnball.gif'
+ : 'redball.gif';
+ $html = sprintf(
+ '<a href="%s"><img border="0" src="%sToolkit/Toolbox/assets/%s"></a>',
+ $link,
+ MEDIA_BASE_URL,
+ $ball
+ );
+ return $html;
+ }
+
+ /**
+ * Handles setting the query for the datagrid
+ *
+ * @return void
+ */
+ public function setQuery()
+ {
+ $sql = "
+ SELECT *
+ FROM videos";
+
+ parent::setQuery($sql);
+ }
+
+ /**
+ * Handles creation of the HTML for the datagrid
+ *
+ * @return string
+ */
+ public function toHtml()
+ {
+ $GLOBALS['styleSheets'][]
+ = MEDIA_BASE_URL . 'Toolkit/Videos/styles.css';
+ $GLOBALS['styleSheets'][]
+ = MEDIA_APP_BASE_URL . 'gallery/colorbox/colorbox.css';
+ $GLOBALS['bottomScripts'][]
+ = MEDIA_APP_BASE_URL . 'libjs/plugins/colorbox/1.3.15/jquery.colorbox-min.js';
+ $GLOBALS['bottomScripts'][]
+ = MEDIA_BASE_URL . 'Toolkit/Videos/libjs/videos.js';
+ return parent::toHTML();
+ }
+
+}
--- /dev/null
+<?php
+
+/**
+ * WebDecorator.php
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+
+/**
+ * Toolkit_Videos_WebDecorator
+ *
+ * Handles the listing of the videos using the PEAR::Structures_DataGrid
+ * extended from our class Toolkit_DataGridBuilder
+ *
+ * @category Toolkit
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2008 Gaslight media
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+class Toolkit_Videos_WebDecorator
+ implements Toolkit_Videos_IDecorator
+{
+
+ private $_flexyOptions = array();
+ private $_template = 'webDecorator.html';
+
+ /**
+ * Class Constructor
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->setFlexyOptions();
+ }
+
+ /**
+ * Handles setting the flexyOptions
+ *
+ * @return void
+ */
+ public function setFlexyOptions()
+ {
+ $this->_flexyOptions = $GLOBALS['flexyOptions'];
+ $this->_flexyOptions['templateDir']
+ = BASE . 'Toolkit/Videos/templates';
+ $this->_flexyOptions['compileDir']
+ = BASE . 'Toolkit/Videos/templates/compiled';
+ }
+
+ /**
+ * Handles HTML output
+ *
+ * @param PDO $dbh Database Connection
+ * @param type $gateway Gateway object
+ *
+ * @return boolean
+ */
+ public function toHtml(
+ PDO $dbh,
+ $gateway = null
+ ) {
+ try {
+ $sql = "
+ SELECT id
+ FROM videos
+ WHERE featured = true
+ ORDER BY pos
+ LIMIT 1
+ OFFSET 0";
+ $row = $dbh->query($sql)->fetch(PDO::FETCH_ASSOC);
+ if ($row) {
+ $tpl = new HTML_Template_Flexy($this->_flexyOptions);
+ $page = new stdClass;
+ $page->videoUrl = Toolkit_Template_Page::getSeoUrl($gateway, 189);
+ $videoMapper
+ = new Toolkit_Videos_VideoMapper($dbh);
+ $video = $videoMapper->getVideoById($row['id'], false);
+ if ($video) {
+ $page->vCode = $video->getVideoCode();
+ $page->title = $video->getVideoTitle();
+ }
+
+ $tpl->compile($this->_template);
+ return $tpl->bufferedOutputObject($page);
+ } else {
+ return false;
+ }
+ } catch(PDOException $e) {
+ Toolkit_Common::handle_error($e);
+ }
+ }
+
+}
--- /dev/null
+<?php
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+/**
+ * WebPageDecorator
+ *
+ * PHP version 5
+ *
+ * @category Category
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2009 Gaslight Media
+ * @license Gaslight Media
+ * @version CVS: $Id: Display.php,v 1.10 2010/07/04 23:55:12 jamie Exp $
+ * @link <>
+ */
+
+/**
+ * WebPageDecorator
+ *
+ * Description of class
+ *
+ * @category Category
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2009 Gaslight Media
+ * @license Gaslight Media
+ * @link <>
+ */
+class Toolkit_Videos_WebPageDecorator implements Toolkit_Videos_IDecorator
+{
+ private $_flexyOptions = array();
+ private $_template = 'webPageDecorator.html';
+ private $_perRow = 5;
+
+ public function __construct()
+ {
+ $this->setFlexyOptions();
+ }
+
+ public function setFlexyOptions()
+ {
+ $this->_flexyOptions = $GLOBALS['flexyOptions'];
+ $this->_flexyOptions['templateDir']
+ = BASE . 'Toolkit/Videos/templates';
+ $this->_flexyOptions['compileDir']
+ = BASE . 'Toolkit/Videos/templates/compiled';
+ }
+
+ public function toHtml(
+ PDO $dbh,
+ $gateway = null
+ ) {
+ $GLOBALS['styleSheets'][]
+ = MEDIA_APP_BASE_URL . 'gallery/colorbox/colorbox.css';
+ $GLOBALS['bottomScripts'][]
+ = MEDIA_APP_BASE_URL . 'libjs/plugins/colorbox/1.3.15/jquery.colorbox-min.js';
+ $GLOBALS['bottomScripts'][]
+ = MEDIA_BASE_URL . 'Toolkit/Videos/libjs/videos.js';
+ $dbh = Toolkit_Database::getInstance();
+ $sql = "
+ SELECT id
+ FROM videos
+ WHERE active = true
+ ORDER BY pos";
+ $stmt = $dbh->query($sql);
+ $page = new stdClass;
+ $page->videos = array();
+ while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $videoMapper
+ = new Toolkit_Videos_VideoMapper($dbh);
+ $video = $videoMapper->getVideoById($row['id'], false);
+ if ($video) {
+ $page->videos[] = array(
+ 'title' => $video->getVideoTitle(),
+ 'code' => $video->getVideoCode()
+ );
+ }
+ }
+ $count = 1;
+ $trueCount = 1;
+ $num = count($page->videos);
+ foreach ($page->videos as &$row) {
+ $row['firstInRow'] = ($count == 1);
+ if ($count == $this->_perRow || $trueCount == $num) {
+ $row['lastInRow'] = true;
+ $count = 0;
+ } else {
+ $row['lastInRow'] = false;
+ }
+ ++$count;
+ ++$trueCount;
+ }
+ $tpl = new HTML_Template_Flexy($this->_flexyOptions);
+ $tpl->compile($this->_template);
+ return $out . $tpl->bufferedOutputObject($page);
+ }
+}
--- /dev/null
+[conf]
+applicationName = "Videos"
+featuredVideos = Off
+
+[listing type]
+singular = "Video"
+plural = "Videos"
--- /dev/null
+var GLMColorBox = {
+ init: function() {
+ $('a.colorbox').colorbox({iframe: true, innerWidth:425, innerHeight:344});
+ $('select.posSelect').each(function () {
+ $(this).change(function(){
+ var id = $(this).attr('rel');
+ var newpos = $(this).attr('value');
+ window.location.href = '../video-move/' + id + '/' + newpos + '/';
+ });
+ });
+ }
+};
+
+$(document).ready(GLMColorBox.init);
--- /dev/null
+<?php
+
+/**
+ * VideosDataGrid.php
+ *
+ * Handles moving the video positions
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+if (!isset($_GET['kpass'])) {
+ die();
+}
+require_once '../../setup.phtml';
+
+$dbh = Toolkit_Database::getInstance();
+$newpos = $_REQUEST['newpos'];
+$id = $_REQUEST['id'];
+$error = false;
+try {
+ $dbh->beginTransaction();
+ $sql = "
+ SELECT pos
+ FROM videos
+ WHERE id = :id";
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(
+ ":id", $_REQUEST['id'], PDO::PARAM_INT
+ );
+ $stmt->execute();
+ $oldpos = $stmt->fetchColumn();
+ if ($oldpos < $newpos) {
+ $sql = "
+ UPDATE videos
+ SET pos = pos - 1
+ WHERE pos BETWEEN :oldpos AND :newpos";
+ $updateStmt = $dbh->prepare($sql);
+ } else if ($oldpos > $newpos) {
+ $sql = "
+ UPDATE videos
+ SET pos = pos + 1
+ WHERE pos BETWEEN :newpos AND :oldpos";
+ $updateStmt = $dbh->prepare($sql);
+ } else {
+ $error = true;
+ }
+
+ if (!$error) {
+ $updateStmt->bindParam(
+ ':newpos', $newpos, PDO::PARAM_INT
+ );
+ $updateStmt->bindParam(
+ ':oldpos', $oldpos, PDO::PARAM_INT
+ );
+ $updateStmt->execute();
+ // now change the real video to its position
+ $sql = "
+ UPDATE videos
+ SET pos = :pos
+ WHERE id = :id";
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(
+ ':pos', $newpos, PDO::PARAM_INT
+ );
+ $stmt->bindParam(
+ ':id', $id, PDO::PARAM_INT
+ );
+ $stmt->execute();
+ }
+ $dbh->commit();
+} catch (PDOException $e) {
+ $dbh->rollback();
+ Toolkit_Logger::logException('DB Error', $e);
+}
+
+header('Location: '.MEDIA_BASE_URL.'admin/videos.php');
--- /dev/null
+#form-warning-top {
+ color: #FF0000;
+ font-size: 14px;
+ font-weight: bold;
+ margin-bottom: 0.5em;
+ margin-top: 1em;
+}
+.required, .req {
+ color: #FF0000;
+}
+.group {
+ display: -moz-inline-box;
+ width: 100%;
+}
+.group td {
+ width: 324px;
+}
+.requiredNote {
+ text-align: center;
+}
+#contact {
+ margin: 10px;
+}
+#contact table {
+ background-color: #FFFFFF;
+ border: 1px solid #EEEEEE;
+ border-collapse: collapse;
+}
+#contact td {
+ border: 1px solid #EEEEEE;
+ border-collapse: collapse;
+ color: #000000;
+ font-family: arial, helvetica, sans-serif;
+ padding: 3px;
+ font-size: 12px;
+}
+.labelcell {
+ background-color: transparent;
+ padding-right: 10px;
+ padding-top: 3px;
+ text-align: right;
+ white-space: nowrap;
+ width: 140px;
+}
+.fieldcell {
+ padding-left: 4px;
+ width: 320px;
+}
+.fieldcell .text {
+ width: 90%;
+}
+#contact table.group {
+ font-size: 10px;
+ border: none;
+ padding-top: 4px;
+}
+#contact table.group td {
+ border: none;
+}
+#contact .hdr {
+ background-color: #999999;
+ border: 1px solid #666666;
+ font-weight: bold;
+}
+.paging {
+ text-align: center;
+ background-color: #F6F6F6;
+ border-color: #E86a10;
+ border-color: #296DC0;
+ border-style: solid;
+ border-width: 1px 0;
+ margin: 1.0em 0;
+ padding: 8px 0;
+ text-align: center;
+ width: 100%;
+ font-size: 12px;
+
+}
+.paging b {
+ border: 1px solid #b22c2c;
+ border: 1px solid #E86A10;
+ background: #FFF;
+ padding: 5px 7px;
+ margin: 0 5px;
+}
+.paging a {
+ background: #FFF;
+ border: 1px solid #CCC;
+ padding: 5px 7px;
+ text-decoration: none;
+ font-family: helvetica, times;
+ color: #000;
+ margin: 0 5px;
+}
+.paging a:hover {
+ border: 1px solid #999;
+ border: 1px solid #b22c2c;
+ border: 1px solid #E86A10;
+}
+#dataGrid {
+ margin: 10px auto;
+ border: 1px solid #296DC0;
+ width: 100%;
+ border-collapse: collapse;
+}
+#dataGrid thead th {
+ background: #296DC0;
+ border: 1px solid #1b4880;
+ color: #000;
+ font-weight: normal;
+}
+#dataGrid th a {
+ font-weight: bolder;
+ color: #000;
+ text-decoration: none;
+}
+#dataGrid th a:hover {
+ color: #E86A10;
+ text-decoration: underline;
+}
+#dataGrid tr {
+ border: 1px solid #296DC0;
+ border-collapse: collapse;
+}
+#dataGrid tbody tr td {
+ padding: 5px;
+}
+#dataGrid .editLink, #dataGrid .delLink,
+#dataGrid .mailLink, #dataGrid .dateLink,
+#dataGrid .posLink {
+ text-align: center;
+}
+img.status {
+ border: none;
+}
+.even {
+ background-color: #D9D9D9;
+}
+#gridSorter {
+ margin: 0 auto;
+ padding: 10px;
+ text-align: center;
+ border: 1px solid #296DC0;
+}
+#gridSorter table {
+ border: none;
+}
+#gridSorter td {
+ border: none;
+}
+.fieldcell textarea {
+ width: 90%;
+ height: 70px;
+}
--- /dev/null
+<div id="v" class="hBox">
+ <h2>Check out our Video Spotlight</h2>
+ <h3>{title:h}</h3>
+ <a href="http://www.youtube.com/embed/{vCode}?rel=0&hd=1" class="colorbox">
+ <img src="http://img.youtube.com/vi/{vCode}/0.jpg" width="400">
+ <img src="assets/videoOverlay.png" width="400" id="videoOverlay">
+ </a>
+ <p>
+ <a href="{videoUrl}">See All Our Videos</a>
+ </p>
+</div>
--- /dev/null
+<div id="videoGallery">
+ {foreach:videos,v}
+ {if:v[firstInRow]}<div class="vRow">{end:}
+ <div class="vThumb">
+ <a href="http://www.youtube.com/embed/{v[code]}?rel=0&hd=1" class="colorbox">
+ <img src="http://img.youtube.com/vi/{v[code]}/default.jpg">
+ </a>
+ <div class="vTitle">
+ {v[title]:h}
+ </div>
+ </div>
+ {if:v[lastInRow]}</div><!-- /.galleryRow --> {end:}
+ {end:}
+</div>
--- /dev/null
+<?php
+
+/**
+ * VideosDataGrid.php
+ *
+ * Handles switching the active flag for the video
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+if (!isset($_GET['kpass'])) {
+ die();
+}
+require_once '../../setup.phtml';
+
+$dbh = Toolkit_Database::getInstance();
+$id = $_REQUEST['id'];
+
+try {
+ $dbh->beginTransaction();
+ $sql = "
+ SELECT active
+ FROM videos
+ WHERE id = :id";
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(
+ ":id",
+ $_REQUEST['id'],
+ PDO::PARAM_INT
+ );
+ $stmt->execute();
+ $activeState = $stmt->fetchColumn();
+
+ if ($activeState) {
+ $sql = "
+ UPDATE videos
+ SET active = false
+ WHERE id = :id";
+ $updateStmt = $dbh->prepare($sql);
+ } else {
+ $sql = "
+ UPDATE videos
+ SET active = true
+ WHERE id = :id";
+ $updateStmt = $dbh->prepare($sql);
+ }
+
+ $updateStmt->bindParam(
+ ':id',
+ $id,
+ PDO::PARAM_INT
+ );
+ $updateStmt->execute();
+ $dbh->commit();
+} catch (PDOException $e) {
+ $dbh->rollback();
+ Toolkit_Logger::logException('DB Error', $e);
+}
+
+header('Location: '.MEDIA_BASE_URL.'admin/videos.php');
--- /dev/null
+<?php
+
+/**
+ * VideosDataGrid.php
+ *
+ * Handles switching the featured flag for the video
+ *
+ * PHP version 5
+ *
+ * @category Toolkit
+ * @package Videos
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @link http://demo.gaslightmedia.com
+ */
+if (!isset($_GET['kpass'])) {
+ die();
+}
+require_once '../../setup.phtml';
+
+$dbh = Toolkit_Database::getInstance();
+$id = $_REQUEST['id'];
+
+try {
+ $dbh->beginTransaction();
+ $sql = "
+ SELECT featured
+ FROM videos
+ WHERE id = :id";
+ $stmt = $dbh->prepare($sql);
+ $stmt->bindParam(
+ ":id",
+ $_REQUEST['id'],
+ PDO::PARAM_INT
+ );
+ $stmt->execute();
+ $featuredState = $stmt->fetchColumn();
+
+ if ($featuredState) {
+ $sql = "
+ UPDATE videos
+ SET featured = false
+ WHERE id = :id";
+ $updateStmt = $dbh->prepare($sql);
+ } else {
+ $sql = "
+ UPDATE videos
+ SET featured = true
+ WHERE id = :id";
+ $updateStmt = $dbh->prepare($sql);
+ }
+
+ $updateStmt->bindParam(
+ ':id',
+ $id,
+ PDO::PARAM_INT
+ );
+ $updateStmt->execute();
+ $dbh->commit();
+} catch (PDOException $e) {
+ $dbh->rollback();
+ Toolkit_Logger::logException('DB Error', $e);
+}
+
+header('Location: '.MEDIA_BASE_URL.'admin/videos.php');
--- /dev/null
+<?php
+
+/**
+ * contact_inquiry.phtml
+ *
+ * Groups are now added to the contact inquiry types. Groups is a
+ * required field.
+ *
+ * PHP versions 4 and 5
+ *
+ * @category Toolkit
+ * @package Contacts
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2009 Gaslight Media
+ * @license Gaslight Media
+ * @version CVS: $Id: contact_inquiry.phtml,v 1.3 2009/07/24 14:27:45 matrix Exp $
+ * @link http://pear.php.net/package/Contacts
+ * @see References to other sections (if any)...
+ */
+
+/**
+ * base setup file for all apps
+ */
+require_once '../../setup.phtml';
+
+/**
+ * base setup for contact admin section
+ */
+require_once "contact_setup.inc";
+GLM_TOOLBOX::top('Contact Inquiries', '');
+// Adjust the nav for this page, add the Edit Groups page.
+if (is_array($nav) && array_key_exists('Contact Inquiry Fields', $nav)) {
+ $tmp = array('Inquiry Groups' => 'list_groups.php');
+ array_insert($nav, 'Contact Inquiry Fields', $tmp);
+}
+GLM_TOOLBOX::html_nav_table($nav, $navWidth);
+$qs = "
+ SELECT id, header, groupid, pos
+ FROM contact_inq
+ ORDER BY groupid, pos;";
+$result = $DB->db_exec($qs);
+$query = "
+ SELECT id, name
+ FROM inq_group
+ ORDER BY name;";
+if ($groupData = $DB->db_auto_get_data($query)) {
+ foreach ($groupData as $groupRow) {
+ $gRow[$groupRow['id']] = $groupRow['name'];
+ }
+}
+?>
+<table id="admin-list-table">
+ <tr>
+ <th colspan="4">
+ <form action="edit_inquiry.phtml" method="POST" name="edit_inquiry">
+ <input type="submit" name="Command" value="Add Item" />
+ </form>
+ </th>
+ </tr>
+ <tr>
+ <th>Options:</th>
+ <th>Pos:</th>
+ <th>Group:</th>
+ <th>Inquiry Name:</th>
+ </tr>
+<?php
+$num = $DB->db_numrows($result);
+if ($num > 0) {
+ for ($i = 0; $i < $num; $i++) {
+ $data = $DB->db_fetch_array($result, $i, PGSQL_ASSOC);
+ if ($data['groupid'] != $oldgroup && isset($oldgroup)) {
+ echo '<tr><td colspan="4"> </td></tr>';
+ }
+ ?>
+ <tr>
+ <td nowrap>
+ <a href="edit_inquiry.phtml?id=<?php echo $data['id'];?>&Command=Edit">[Edit / Delete]</a>
+ </td>
+ <td>
+ <?php
+ $qs = "
+ SELECT COUNT(id) AS maxpos
+ FROM contact_inq
+ WHERE groupid = ".$data['groupid'];
+
+ $maxresult = $DB->db_exec($qs);
+ $max_data = $DB->db_fetch_array($maxresult, 0, PGSQL_ASSOC);
+ $maxpos = $max_data['maxpos'];
+ $pos = '<select style="font-size: 10pt;" name="pos"
+ onChange="location.href=this[this.selectedIndex].value;"
+ size="1">';
+ for ($newpos = 1; $newpos <= $maxpos; $newpos++) {
+ $string = 'Command=Move&groupid='.$data['groupid'].'&id='.$data['id']."&newpos=$newpos";
+ $pos .= "<option value=\"update_inquiry.phtml?$string\"";
+ if ($newpos == $data['pos']) {
+ $pos .= ' selected';
+ }
+ $pos .= ">$newpos</option>";
+ }
+ $pos .= '</select>';
+ echo $pos;
+ ?>
+ </td>
+ <td nowrap>
+ <?php echo $gRow[$data['groupid']];?>
+ </td>
+ <td align="left">
+ <?php echo $data['header'];?>
+ </td>
+ </tr>
+ <?php
+ $oldgroup = $data['groupid'];
+ }
+} else {
+ ?>
+ <tr>
+ <th colspan="2">Nothing in the database yet</th>
+ </tr>
+ <?php
+}
+?>
+</table>
+<?php
+GLM_TOOLBOX::footer();
+?>
--- /dev/null
+<?php
+
+/**
+* contact_setup.phtml
+*
+* Config setting for the admin contact application
+*
+* PHP versions 4 and 5
+*
+* @category Toolkit
+* @package Contacts
+* @author Steve Sutton <steve@gaslightmedia.com>
+* @copyright 2009 Steve Sutton
+* @license Gaslight Media
+* @version CVS: $Id: contact_setup.inc,v 1.7 2010/05/13 17:05:53 matrix Exp $
+* @link <>
+*/
+extract($_REQUEST);
+// The Contact Type array is now is one location and is used by the
+// Toolkit_Contacts_Admin_EditContact class
+$conf = new Config;
+$contactRoot =& $conf->parseConfig(
+ BASE . 'Toolkit/Contacts/config.ini',
+ 'IniFile'
+);
+if (!defined("ENTRIES_PER_PAGE")) {
+
+ /**
+ * how many per page on list contacts
+ */
+ define("ENTRIES_PER_PAGE", 10); // Entries per Page in list_contact.phtml
+}
+
+/**
+* define for customer table
+*/
+define("CUSTOMER_TABLE", "customer"); // name of customer table
+
+/**
+* define for contact table
+*/
+define("CONTACT_TABLE", "contact"); // name of contact table
+
+$table = $contactRoot->getItem('section', 'conf')
+ ->getItem('directive', 'table')
+ ->getContent();
+/**
+* Table to user in db
+*/
+define("TABLE", $table); // which table to use
+
+/**
+* postgres date formate
+*/
+define("DATEFORMAT", "US"); // date format (for edit_contact.phmtl)
+
+/**
+* template for the newsletter
+*/
+define("NEWSLETTER_PROTOTYPE", "newsletter_template.html"); // date format (for edit_contact.phmtl)
+
+/**
+* class_template needed for GLM_TEMPLATE::get_seo_url()
+*/
+require_once BASE.'classes/class_template.inc';
+$DB = new GLM_DB();
+if (!defined("HTML_EMAIL")) {
+
+ /**
+ * HTML_EMAIL = ON or OFF
+ */
+ define("HTML_EMAIL", "ON");
+}
+if (!defined("PRODUCTION_MODE")) {
+
+ /**
+ * PRODUCTION_MODE off/on mail sent
+ */
+ define("PRODUCTION_MODE", "ON");
+}
+if (!defined("NEWSLETTER")) {
+
+ /**
+ * NEWSLETTER 1 or true will allow newsletters
+ */
+ define("NEWSLETTER", 1); //bool- does the contact database mail out a newsletter?
+}
+
+if (!function_exists("template_read")) {
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param unknown $template Parameter description (if any) ...
+ *
+ * @return string Return description (if any) ...
+ */
+ function template_read($template)
+ {
+ $fp = fopen($template, "r");
+ $contents = fread($fp, filesize($template));
+ fclose($fp);
+ if ($contents) {
+ return $contents;
+ } else {
+ return "";
+ }
+ }
+}
+// {{{ array_insert()
+
+
+/**
+* insert an array into another array after position.
+* You can specify an associative array key or index key
+* to dictact the positioning of the new array
+*
+* @param array &$array array to be used
+* @param unknown $position position to add array
+* @param unknown $insert_array array to be inserted
+*
+* @return void
+*/
+function array_insert(&$array, $position, $insert_array)
+{
+ if (!is_int($position)) {
+ $i = 0;
+ foreach ($array as $key => $value) {
+ if ($key == $position) {
+ $position = ++$i;
+ break;
+ }
+ ++$i;
+ }
+ }
+ $first_array = array_splice($array, 0, $position);
+ $array = array_merge($first_array, $insert_array, $array);
+}
+// }}}
+// {{{ explode_template()
+if (!function_exists("explode_template")) {
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param unknown $template Parameter description (if any) ...
+ * @param unknown $data Parameter description (if any) ...
+ *
+ * @return unknown Return description (if any) ...
+ */
+ function explode_template($template, $data)
+ {
+ $template = template_read($template);
+ $output = template_replacement($template, $data);
+ $output = wordwrap($output, 72);
+ return $output;
+
+ }
+}
+// }}}
+// {{{ template_replacement($template, $fieldarr)
+if (!function_exists("template_replacement")) {
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param unknown $template Parameter description (if any) ...
+ * @param array $fieldarr Parameter description (if any) ...
+ *
+ * @return unknown Return description (if any) ...
+ */
+ function template_replacement($template, $fieldarr)
+ {
+ if (is_array($fieldarr)) {
+ foreach ($fieldarr as $key => $value) {
+ $template = str_replace("<!-- ".$key." -->", $value, $template);
+ }
+ }
+ return $template;
+ }
+}
+// }}}
+// {{{ add_image($image, $align)
+if (!function_exists("add_image")) {
+
+ /**
+ * Short description for function
+ *
+ * Long description (if any) ...
+ *
+ * @param string $image Parameter description (if any) ...
+ * @param string $align Parameter description (if any) ...
+ *
+ * @return string Return description (if any) ...
+ */
+ function add_image($image, $align)
+ {
+ if ($image != "") {
+ return '<div style="margin:5px;float:'.$align.';"><img src="'.MIDSIZED.$image.'"></div>';
+ }
+ }
+}
+// }}}
+// {{{ Navigation array
+$nav = array(
+ "Report Builder" => "index.phtml",
+ "Add Contact" => "edit_contact.php",
+ "List Contacts" => "list_contact.phtml",
+ "Contact Inquiry Fields" => "contact_inquiry.phtml",
+ "HTML Emails" => "emails.php",
+ "Saved Reports" => "list_query.phtml",
+);
+// }}}
+$navWidth = 7;
+$query = "select * from contact_inq order by pos;";
+$cData = $DB->db_auto_get_data($query);
+if (is_array($cData)) {
+ foreach ($cData as $key => $value) {
+ $int_array[$value['id']] = $value['header'];
+ }
+}
+$contactTypesSetup =
+ $contactRoot->getItem('section', 'contact_types')
+ ->toArray();
+$cType = $contactTypesSetup['contact_types'];
+// {{{ search_where($name, $search_where)
+
+/**
+* Short description for function
+*
+* Long description (if any) ...
+*
+* @param string $name Parameter description (if any) ...
+* @param string $search_where Parameter description (if any) ...
+*
+* @return string Return description (if any) ...
+*/
+function search_where($name, $search_where)
+{
+ $out = '
+ <select name="'.$name.'">
+ <option value="1" '.( ( !isset( $search_type ) || $search_type == "0" ) ? 'selected' : '' ).'>Anywhere
+ <option value="2" '.( ( $search_where == '1' ) ? 'selected' : '' ).'>Begining
+ <option value="3" '.( ( $search_where == '2' ) ? 'selected' : '' ).'>Ending
+ </select>';
+ return $out;
+}
+// }}}
+// {{{ search_type($name, $search_type)
+
+/**
+* Short description for function
+*
+* Long description (if any) ...
+*
+* @param string $name Parameter description (if any) ...
+* @param string $search_type Parameter description (if any) ...
+*
+* @return string Return description (if any) ...
+*/
+function search_type($name, $search_type)
+{
+ $out = '
+ <select name="'.$name.'">
+ <option value="2" '.( ( !isset( $search_type ) || $search_type == '2' ) ? 'selected' : '' ).'>And
+ <option value="3" '.( ( $search_type == '3' ) ? 'selected' : '' ).'>Or
+ <option value="4" '.( ( $search_type == '4' ) ? 'selected' : '' ).'>Not
+ </select>';
+ return $out;
+}
+// }}}
+// {{{ search_bool($name, $search_type)
+
+/**
+* Short description for function
+*
+* Long description (if any) ...
+*
+* @param string $name Parameter description (if any) ...
+* @param string $search_type Parameter description (if any) ...
+*
+* @return string Return description (if any) ...
+*/
+function search_bool($name, $search_type)
+{
+ $out = '
+ <select name="'.$name.'">
+ <option value="n" '.( !isset( $search_type ) ? 'selected' : '' ).'>Don\'t Care
+ <option value="1" '.( ( $search_type == '1' ) ? 'selected' : '' ).'>Yes
+ <option value="0" '.( ( $search_type == '0' ) ? 'selected' : '' ).'>No
+ </select>';
+ return( $out );
+}
+// }}}
+// {{{ interest($field)
+
+/**
+* Short description for function
+*
+* Long description (if any) ...
+*
+* @param unknown $field Parameter description (if any) ...
+*
+* @return boolean Return description (if any) ...
+*/
+function interest($field)
+{
+ if (!is_array($GLOBALS['int_array'])) {
+ return false;
+ }
+ echo "<table><tr>";
+ $count = 0;
+ foreach ($GLOBALS['int_array'] as $key => $value) {
+ if ($count==0) {
+ echo "<td>";
+ }
+ echo "<input type=\"checkbox\" name=\"interest[]\" value=\"$key\"";
+ if (strstr($field, ":".$key.":")) {
+ echo " checked";
+ }
+ echo ">$value<br>";
+ if ($count==5) {
+ echo "</td><td>";
+ }
+ if ($count==11) {
+ echo "</td>";
+ }
+ $count++;
+ }
+ echo "</tr></table>";
+}
+/**
+* Get a group of select elements to represent a date
+*
+* @param string $M Name attribute of the month select list
+* @param string $D Name attribute of the day select list
+* @param string $Y Name attribute of the year select list
+* @param string $m Selected value of the month select list
+* @param string $d Selected value of the day select list
+* @param string $y Selected value of the year select list
+*
+* @return string Html string of group select lists
+* @access public
+*/
+function dateSelector($M, $D, $Y, array $m = null, array $d = null, array $y = null)
+{
+ // Get a Select element
+ $month = new HTML_Select($M);
+ // Get a Range of months jan-dec
+ $monthArray = array_flip(range(1, 12));
+ // Make the keys and values the same
+ foreach ($monthArray as $i => &$j) {
+ $j = $i;
+ }
+ $month->loadArray($monthArray);
+ if (is_null($m)) {
+ $month->setSelectedValues(array(date('m')));
+ } else {
+ $month->setSelectedValues($m);
+ }
+
+ // Get a Select element
+ $day = new HTML_Select($D);
+ // Get a Range of months jan-dec
+ $dayArray = array_flip(range(1, 31));
+ // Make the keys and values the same
+ foreach ($dayArray as $i => &$j) {
+ $j = $i;
+ }
+ $day->loadArray($dayArray);
+ if (is_null($d)) {
+ $day->setSelectedValues(array(date('d')));
+ } else {
+ $day->setSelectedValues($d);
+ }
+
+ // Get a Select element
+ $year = new HTML_Select($Y);
+ // Get a Range of months jan-dec
+ $yearArray = array_flip(range(CONTACTS_FIRST_YEAR, date('Y')));
+ // Make the keys and values the same
+ foreach ($yearArray as $i => &$j) {
+ $j = $i;
+ }
+ $year->loadArray($yearArray);
+ if (is_null($y)) {
+ $year->setSelectedValues(array(date('Y')));
+ } else {
+ $year->setSelectedValues($y);
+ }
+
+ return $month->toHtml() . $day->toHtml() . $year->toHtml();
+}
+
+// }}}
+// default query on create_date
+$c_date_from = GLM_TOOLBOX::contact_date_entry("", "", "", "fc_month", "fc_day", "fc_year");
+$c_date_to = GLM_TOOLBOX::contact_date_entry("", "", "", "tc_month", "tc_day", "tc_year");
+
+// The Following $DB_fields array is no longer used for the edit contact page
+// You must alter the class Toolkit_Contacts_Admin_EditContact
+// The following is only used for the search form and the listing pages
+
+$primaryKey = $contactRoot->getItem('section', 'conf')
+ ->getItem('directive', 'primarykey')
+ ->getContent();
+/**
+* Description for define
+*/
+define("ID", $primaryKey);
+
+/**
+* Description for define
+*/
+define("MAILOK", "mail_ok");
+
+$sequence = $contactRoot->getItem('section', 'conf')
+ ->getItem('directive', 'sequence')
+ ->getContent();
+/**
+* Description for define
+*/
+define("SEQUENCE", $sequence);
+
+/**
+* Description for define
+*/
+define("WHERE", ID." IS NOT NULL");
+// $DB_fields are used for edit and updating contacts
+$DB_fields[] = array("name" => "id", "title" => "id", "type" => "hide");
+$DB_fields[] = array("name" => "create_date", "title" => "Create Date", "type" => "static");
+$DB_fields[] = array("name" => "fname", "title" => "First Name", "type" => "text");
+$DB_fields[] = array("name" => "lname", "title" => "Last Name", "type" => "text");
+if (TABLE == 'customer') {
+ $DB_fields[] = array("name" => "add1", "title" => "Address", "type" => "text");
+ $DB_fields[] = array("name" => "add2", "title" => "Address 2", "type" => "text");
+} else {
+ $DB_fields[] = array("name" => "company", "title" => "Company Name", "type" => "text");
+ $DB_fields[] = array("name" => "address", "title" => "Address", "type" => "text");
+ $DB_fields[] = array("name" => "address2", "title" => "Address 2", "type" => "text");
+}
+$DB_fields[] = array("name" => "city", "title" => "City", "type" => "text");
+$DB_fields[] = array("name" => "state", "title" => "State", "type" => "state");
+$DB_fields[] = array("name" => "zip", "title" => "Zip", "type" => "text");
+$DB_fields[] = array("name" => "phone", "title" => "Phone", "type" => "text");
+$DB_fields[] = array("name" => "fax", "title" => "Fax", "type" => "text");
+$DB_fields[] = array("name" => "email", "title" => "Email", "type" => "text");
+$DB_fields[] = array("name" => "mail_ok", "title" => "Mail Ok?", "type" => "radio");
+$DB_fields[] = array("name" => "interest", "title" => "Interest", "type" => "interest");
+$DB_fields[] = array("name" => "contact_type", "title" => "Contact Type", "type" => "drop", "drop" => $cType);
+
+// $fields are used for building the query page
+foreach ($DB_fields as $key=>$value) {
+ if ($value['type'] == "text" || $value['type'] == "state") {
+ $fields[$value['name']] = $value['title'];
+ } elseif ( $value['type'] == "radio") {
+ $boolean[$value['name']] = $value['title'];
+ } elseif ( $value['type'] == "drop") {
+ $dropdowns[$value['name']] = array('title' => $value['title'], 'drop' => $value['drop']);
+ }
+}
+
+$data['bailout'] .= "You are receiving this message because you have expressed an interest in ";
+$data['bailout'] .= "receiving specials and information from ".SITENAME.". If you do not ";
+$data['bailout'] .= "wish to receive future items of this nature, please reply to this e-mail ";
+$data['bailout'] .= "with the word \"CANCEL\" on the subject line. You will then be removed ";
+$data['bailout'] .= "from future mailings.<br>";
+$data['bailout'] .= "<a href=\"mailto:".OWNER_EMAIL."?subject=CANCEL\">".OWNER_EMAIL."</a><br>";
+?>
--- /dev/null
+<?php
+//$Id: del_query.phtml,v 1.2 2009/05/20 20:27:27 matrix Exp $
+include "../../setup.phtml";
+include "contact_setup.inc";
+
+$qs = "DELETE
+ FROM query_db
+ WHERE id = $id";
+
+if(!$DB->db_auto_exec($qs)) {
+ GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,1);
+}
+GLM_TOOLBOX::html_header("Admin","Deleted","");
+?>
+<script lang="javascript">
+document.onload=window.opener.location.reload(1);
+</script>
+Query <?php echo $id?> is Deleted
+<center><a href="" onClick="window.close();return(false);">Close This
+Window</a></center>
--- /dev/null
+<?php
+
+/**
+ * download.phtml
+ *
+ * gives admin user ability to download a csv file for import into
+ * another source. Forces the save as dialog box.
+ * tested on ie6 ie7 and firefox. $query_string is passed through to
+ * this page by a form.
+ *
+ * PHP versions 4 and 5
+ *
+ * @category Toolkit
+ * @package PackageName
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2009 Gaslight Media
+ * @license Gaslight Media
+ * @version CVS: $Id: download.phtml,v 1.3 2009/08/05 15:15:00 matrix Exp $
+ * @link <>
+ */
+
+/**
+ * main site setup config file
+ */
+require_once "../../setup.phtml";
+
+/**
+ * main contact setup file
+ */
+require_once "contact_setup.inc";
+
+// check that the site sending this request is the same
+// as the base_url
+$base = str_replace("admin/Contact/list_contact.phtml",
+ "",
+ $_SERVER['HTTP_REFERER']
+);
+if ($base != MEDIA_BASE_URL) {
+ // redirect them
+ header("Location: index.phtml");
+}
+
+$delimiter = str_replace("comma", ",", $delimiter);
+$delimiter = str_replace("tab", "\t", $delimiter);
+$delimiter = str_replace("csv", ",", $delimiter);
+$delimiter = str_replace("pipe", "|", $delimiter);
+
+if ($_REQUEST['query_string']) {
+ /* Remove the old reports if they exsists */
+ if (is_file("report.csv")) {
+ unlink("report.csv");
+ }
+ if (is_file("report.tar.gz")) {
+ unlink("report.tar.gz");
+ }
+ if (is_file("report.zip")) {
+ unlink("report.zip");
+ }
+
+ if (!$fp = fopen("report.csv", "w")) {
+ html_error("Cant open report", 0);
+ }
+ $query_string = stripslashes($_REQUEST['query_string']);
+ $query_string = str_replace("SELECT " . ID . ",", "SELECT ", $query_string);
+ $query_string = str_replace(" FROM ",
+ ",contact_type,interest FROM ",
+ $query_string);
+
+ $dbh = Toolkit_Database::getInstance();
+
+ $res = $dbh->prepare($query_string);
+ $res->execute();
+ $total = $res->rowCount();
+ $headers =array();
+ $headerString = '';
+ if ($total > 0) {
+ for ($i = 0; $i < $total; ++$i) {
+ $result_string = "";
+ $row = $res->fetch(PDO::FETCH_ASSOC);
+ $cConTypes = array();
+ foreach ($row as $fieldName => $value) {
+ if ($i == 0) {
+ if (in_array($fieldName, array('contact_type', 'interest'))) {
+ switch ($fieldName) {
+ case 'contact_type' :
+ foreach ($cType as $contactTypeName) {
+ $headers[] = $contactTypeName;
+ }
+ break;
+ case 'interest' :
+ if ( is_array($int_array)
+ && !empty($int_array)
+ ) {
+ foreach ($int_array as $interesName) {
+ $headers[] = $interesName;
+ }
+ }
+ break;
+ }
+ } else {
+ $headers[] = $fieldName;
+ }
+ }
+ // this section creates the contact_type part of the rows
+ // need to make this one a set number of fields for the contact
+ // types needed for all contacts
+ // so create count($cType) number of columns for this one field
+ if ($fieldName == 'contact_type') {
+ $cConTypes = array();
+ $st = array();
+ if (strstr($value, ":")) {
+ $cConTypesStr = preg_replace("/^:|:$/",
+ "",
+ $value
+ );
+ $cConTypes = explode(":", $cConTypesStr);
+ }
+ if (is_array($cType) && !empty($cType)) {
+ foreach ($cType as $contactTypeId => $contactTypeName) {
+ $st[]
+ = ( is_array($cConTypes)
+ && in_array($contactTypeId, $cConTypes))
+ ? $contactTypeName
+ : '';
+ }
+ $result_string .= implode("|", $st);
+ }
+ $result_string .= '|';
+ }
+ // this section creates the interest part of the rows
+ // need to make this one a set number of fields for the contact
+ // types needed for all contacts
+ // so create count($int_array) number of columns for this one field
+ else if ($fieldName == 'interest') {
+ $iIntTypes = array();
+ $st = array();
+ if (strstr($value, ":")) {
+ $iIntTypesStr = preg_replace("/^:|:$/",
+ "",
+ $value);
+ $iIntTypes = explode(":", $iIntTypesStr);
+ }
+ if ( is_array($int_array)
+ && !empty($int_array)
+ ) {
+ foreach ($int_array as $interestId => $interestName) {
+ $st[]
+ = ( is_array($iIntTypes)
+ && in_array($interestId, $iIntTypes))
+ ? $interestName
+ : '';
+ }
+ $result_string .= implode("|", $st);
+ }
+ $result_string .= '|';
+ }
+ // this one deals with al the other fields
+ else if (!in_array($fieldName, array('contact_type', 'interest'))) {
+ $result_string .= $value.'|';
+ }
+ }
+ $result_string = substr($result_string, 0, strlen($result_string)-1);
+ if ($i == 0) {
+ if ($csv) {
+ $headerString = '"'.implode('","', $headers)."\"\n";
+ } else {
+ $headerString = implode($delimiter, $headers)."\n";
+ }
+ fputs($fp, $headerString, strlen($headerString));
+ }
+ if ($csv) {
+ $result_string = str_replace("|", "\",\"", $result_string);
+ $result_string = "\"".$result_string."\"\n";
+ } else {
+ $result_string = str_replace("|", $delimiter, $result_string);
+ $result_string = $result_string."\n";
+ }
+ fputs($fp, $result_string, strlen($result_string));
+ }
+ }
+ if (!fclose($fp)) {
+ html_error("Cant close filepointer", 0);
+ }
+ chmod("report.csv", 0660);
+ $output = "report.csv";
+
+ if ($file == "gz") {
+ $output = "report.tar.gz";
+ exec("tar -czvf report.tar.gz report.csv 2>&1", $result_array, $result);
+ if ($result != 0) {
+ echo $result_array[0];
+ exit;
+ }
+ chmod("report.tar.gz", 0660);
+ }
+
+ if ($file == "zip") {
+ $output = "report.zip";
+ exec("zip report report.csv 2>&1", $result_array, $result);
+ if ($result != 0) {
+ echo $result_array[0];
+ exit;
+ }
+ chmod("report.zip", 0660);
+ }
+ if ($file == "rpt") {
+ $output = "report.csv";
+ chmod("report.csv", 0660);
+ }
+ if (ini_get('zlib.output_compression')) {
+ ini_set('zlib.output_compression', 'Off');
+ }
+ header("Content-Type: application/force-download\n");
+ /* Correction for the stupid MSIE thing */
+ if (strstr(getenv('HTTP_USER_AGENT'), 'MSIE')) {
+ header("Content-Disposition: inline; filename=\"$output\"");
+ } else {
+ header("Content-Disposition: attachment; filename=\"$output\"");
+ }
+ //header("Location: $output");
+ $fn = fopen($output, "r");
+ fpassthru($fn);
+ @fclose($fn);
+ exit();
+} else {
+ header("Location: list_contact.phtml");
+}
+?>
--- /dev/null
+<?php
+//$Id: edit_autoresponse.phtml,v 1.12 2010/08/11 18:16:41 matrix Exp $
+include "../../setup.phtml";
+include "contact_setup.inc";
+GLM_TOOLBOX::top("AutoReponse for Newsletter", HELP_BASE."response.phtml?key=edit+section");
+
+GLM_TOOLBOX::html_nav_table($nav, $navWidth);
+
+if ($id) {
+ $qs = "SELECT id,subject,response
+ FROM news_response
+ WHERE id = $id";
+
+ if (!$res = $DB->db_exec($qs)) {
+ GLM_TOOLBOX::html_error(DB_ERROR_MSG.__LINE__, 1);
+ }
+ $row = $DB->db_fetch_array($res,0, PGSQL_ASSOC);
+} else {
+ $row['subject'] = '';
+ $row['response'] = '';
+}
+?>
+<script src=<?php echo MEDIA_BASE_URL."admin/verify.js";?>></script>
+<script type="text/javascript" src="<?php echo CKEDITOR_JS;?>"></script>
+<script language="javascript">
+<!--// closed source
+function mySubmit(o){
+ o.response.optional = true;
+ o.response.r = 'Description';
+ o.subject.optional = false;
+ o.subject.r = 'Subject';
+ return(verify(o))
+}
+var Newsletter =
+{
+ init: function()
+ {
+ if ($('#response').length) {
+ // Only try to replace the textarea if the
+ // CKEditor is compatible w/ the browser.
+ if (CKEDITOR.env.isCompatible) {
+ CKEDITOR.replace('response',
+ {
+ toolbar : 'Default',
+ width : 570,
+ height : 400,
+ filebrowserImageBrowseUrl : '../../Toolkit/CKImages/browser.php?folder=1',
+ filebrowserImageUploadUrl : '../../Toolkit/CKImages/controller.php?command=Upload',
+ filebrowserImageWindowWidth : '760',
+ filebrowserImageWindowHeight : '500'
+ });
+ }
+ }
+ }
+};
+
+$(document).ready(Newsletter.init);
+
+//-->
+</script>
+<form id="form1" name="form1" enctype="multipart/form-data" action="update_autoresponse.phtml" method="POST">
+<table id="admin-edit-table">
+<?
+foreach ($row as $key => $value) {
+ switch ($key) {
+
+ case "id":
+ echo "<input type=\"hidden\" name=\"id\" value=\"$value\">";
+ break;
+
+ case "subject":
+ echo "<tr><td class=\"navtd\" align=\"right\">Subject:</td>";
+ GLM_TOOLBOX::text_box("subject", $value);
+ echo "</tr>";
+ break;
+
+ case "response":
+ echo "<tr><td class=\"navtd\" align=\"right\">Response:</td>";
+ echo '<td><textarea name="response" id="response" cols="60" rows="60">'.$value.'</textarea></td>';
+ echo "</tr>";
+ break;
+
+ default:
+ break;
+ }
+}
+echo '<tr><td></td><td nowrap="nowrap">';
+if ($id) {
+ ?>
+ <input type="submit" name="Command" value="Update">
+ <?php
+} else {
+ ?>
+ <input type="submit" name="Command" value="Insert">
+ <?php
+}
+echo '
+</td></tr>
+</table>
+</form>';
+GLM_TOOLBOX::footer();
+?>
--- /dev/null
+<?php
+require_once '../../setup.phtml';
+include "contact_setup.inc";
+$form = new Toolkit_Contacts_Admin_EditContact(
+ Toolkit_Database::getInstance(),
+ 'edit_contact'
+);
+$form->setConfig($contactRoot);
+$form->setTableName(
+ $contactRoot->getItem('section', 'conf')
+ ->getItem('directive', 'table')
+ ->getContent()
+);
+$form->setPrimaryKey(
+ $contactRoot->getItem('section', 'conf')
+ ->getItem('directive', 'primarykey')
+ ->getContent()
+);
+
+$form->configureForm($contactRoot);
+$formOutput = $form->toHtml();
+GLM_TOOLBOX::top("Updatable Listings (Add/Edit)", "help/contact.phtml?key=Edit");
+GLM_TOOLBOX::html_nav_table($nav, $navWidth);
+echo $formOutput;
+GLM_TOOLBOX::footer();
--- /dev/null
+<?php
+include "../../setup.phtml";
+include "contact_setup.inc";
+if ($_POST) {
+ $sub_oktogo = true;
+ if (empty($_POST['group'])) {
+ $sub_oktogo = false;
+ }
+ switch ($_POST['Command']) {
+ case 'Add' :
+ $qs = "INSERT INTO inq_group(name) VALUES('".$_POST['group']."')";
+ break;
+
+ case 'Edit' :
+ $qs = "UPDATE inq_group SET name = '".$_POST['group']."' WHERE id = ".$_POST['id'];
+ break;
+
+ case 'Delete' :
+ $qs = "DELETE FROM inq_group WHERE id = ".$_POST['id'];
+ break;
+
+ default :
+ unset($qs);
+ break;
+ }
+ if ($_POST['Command'] == 'Delete') {
+ $DB->db_exec($qs);
+ header('Location: list_groups.php');
+ } else if ($sub_oktogo && isset($qs)) {
+ $DB->db_exec($qs);
+ header('Location: list_groups.php');
+ }
+}
+?>
+<script type="text/javascript">
+function form_sub_check() {
+ var sub_oktogo = true;
+ var group = document.getElementById('group').value;
+ var groupBox = document.getElementById('group_box');
+
+ if (group == '') {
+ groupBox.className = "problem";
+ sub_oktogo = false;
+ problems = '-- Name\n';
+ } else {
+ groupBox.className = '';
+ }
+
+ if (!sub_oktogo)
+ alert('Please give your new group a name before continuing');
+ // Return whether the form will submit or not!
+ return sub_oktogo ? true : false;
+}
+</script>
+<style type="text/css">
+.problem {
+ background-color: #FCA9A4 !important;
+}
+</style>
+<?php
+GLM_TOOLBOX::top('Edit/Add Inquiry','');
+// Adjust the nav for this page, add the Edit Groups page.
+if (is_array($nav) && array_key_exists('Contact Inquiry Fields', $nav)) {
+ $tmp = array('Inquiry Groups' => 'list_groups.php');
+ array_insert($nav, 'Contact Inquiry Fields', $tmp);
+}
+GLM_TOOLBOX::html_nav_table($nav,$navWidth);
+if (is_numeric($_GET['id'])) {
+ $query = 'SELECT * FROM inq_group WHERE id = '.$_GET['id'];
+ if ($data = $DB->db_auto_get_data($query)) {
+ $name = $data[0]['name'];
+ $id = $data[0]['id'];
+ }
+} else {
+ $name = '';
+}
+?>
+<form action="edit_group.php" method="POST" onSubmit="return form_sub_check();">
+ <table id="admin-edit-table">
+ <tr>
+ <th>Group Name:</th>
+ <td id="group_box" <?php echo ($_POST && !$sub_oktogo) ? 'class="problem"' : '';?>>
+ <input type="text" name="group" id="group" value="<?php echo $name;?>">
+ <input type="hidden" name="id" id="id" value="<?php echo $id;?>">
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" align="center">
+ <?php if ($_GET['Command'] == "Edit") :?>
+ <input type="submit" name="Command" value="Edit">
+ <input type="submit" name="Command" value="Delete">
+ <?php else :?>
+ <input type="submit" name="Command" value="Add">
+ <?php endif;?>
+ </td>
+ </tr>
+ </table>
+</form>
+<?php GLM_TOOLBOX::footer();?>
--- /dev/null
+<?php
+require_once "../../setup.phtml";
+require_once "contact_setup.inc";
+GLM_TOOLBOX::top('Edit/Add Inquiry','');
+?>
+<script type="text/javascript">
+ $(document).ready(function(){
+ $('#deleteButton').click(function(){
+ $('input[name="xCommand"]').val('Delete');
+ });
+ });
+function form_sub_check()
+{
+ var submitButton = $('input[name="xCommand"]').val();
+ if (submitButton == 'Delete') {
+ return true;
+ }
+ var sub_oktogo = true;
+ var problems = '';
+ var header = $("#header").val();
+ var headerBox = $("#header_box");
+ var group = $("#groupid").val();
+ var groupBox = $("#group_box");
+ var newGroup = $("#new_group").val();
+
+ if (header == '') {
+ headerBox.addClass("problem");
+ sub_oktogo = false;
+ problems = '-- Name\n';
+ } else {
+ headerBox.removeClass("problem");
+ }
+ if ((group == undefined || group == 0) && newGroup == '') {
+ groupBox.addClass("problem");
+ sub_oktogo = false;
+ problems += '-- Group\n';
+ } else {
+ groupBox.removeClass("problem");
+ }
+ if (!sub_oktogo) {
+ alert('You have problems on your form!\nPlease carefully review the following and re-submit your form.\n\n' + problems);
+ }
+ // Return whether the form will submit or not!
+ return sub_oktogo ? true : false;
+}
+</script>
+<style type="text/css">
+.problem {
+ background-color: #FCA9A4 !important;
+}
+</style>
+<?php
+// Adjust the nav for this page, add the Edit Groups page.
+if (is_array($nav) && array_key_exists('Contact Inquiry Fields', $nav)) {
+ $tmp = array('Inquiry Groups' => 'list_groups.php');
+ array_insert($nav, 'Contact Inquiry Fields', $tmp);
+}
+GLM_TOOLBOX::html_nav_table($nav,$navWidth);
+if (is_numeric($_GET['id'])) {
+ $query = "SELECT * FROM contact_inq WHERE id = $id";
+ if ($data = $DB->db_auto_get_data($query)) {
+ $header = $data[0]['header'];
+ $description = $data[0]['description'];
+ $pos = $data[0]['pos'];
+ $groupid = $data[0]['groupid'];
+ }
+} else {
+ $header = '';
+ $description = '';
+ $groupid = '';
+}
+$query = "SELECT * FROM inq_group ORDER BY name;";
+if ($gData = $DB->db_auto_get_data($query)) {
+ $group_sel = '<select id="groupid" name="groupid">';
+ $group_sel .= '<option value="">New Group - >></option>';
+ foreach ($gData as $gRow) {
+ $group_sel .= '<option value="'.$gRow['id'].'"';
+ if( $groupid && $gRow['id'] == $groupid )
+ {
+ $group_sel .= ' selected';
+ }
+ $group_sel .= '>'.$gRow['name'];
+ $group_sel .= '</option>';
+ }
+ $group_sel .= '</select>';
+}
+?>
+<form action="update_inquiry.phtml" method="POST" onSubmit="return form_sub_check();">
+ <input type="hidden" name="old_groupid" value="<?php echo $groupid;?>" />
+ <table id="admin-edit-table">
+ <tr>
+ <th>Name:</th>
+ <td id="header_box">
+ <input type="text" name="header" id="header" size="50" value="<?php echo $header?>">
+ <input type="hidden" name="id" value="<?php echo $id?>">
+ </td>
+ </tr>
+ <?
+ echo '<input type="hidden" name="oldpos" value="'.$pos.'">';
+ ?>
+ <tr>
+ <th>Group:</th>
+ <td id="group_box">
+ <?php echo $group_sel;?>
+ <input type="text" id="new_group" name="new_group" value="" />
+ </td>
+ </tr>
+ <tr>
+ <td colspan=2 align=center>
+ <input type="hidden" name="xCommand" value="" />
+<?php
+if ($Command == "Edit") {
+ ?>
+ <input type="submit" name="Command" value="Edit">
+ <input type="submit" id="deleteButton" name="Command" value="Delete">
+ <?php
+} else {
+?>
+ <input type="submit" name="Command" value="Add">
+<?php
+}
+?>
+ </td>
+ </tr>
+ </table>
+</form>
+<?php
+GLM_TOOLBOX::footer();
+?>
--- /dev/null
+<?php
+require_once '../../setup.phtml';
+require_once BASE . 'classes/class_db.inc';
+require_once 'contact_setup.inc';
+$DB = new GLM_DB();
+$query = "select * from news_response order by id;";
+$data = $DB->db_auto_get_data( $query );
+GLM_TOOLBOX::top( "Email HTML Newsletters", "");
+GLM_TOOLBOX::html_nav_table($nav,$navWidth);
+$out = '<table id="admin-list-table">
+ <tr><td colspan="2" align="center">
+ <form name="add" action="edit_autoresponse.phtml" method="post">
+ <button name="command" onClick="add.submit()">Add HTML EMAIL</button>
+ </td></tr>
+ <tr>
+ <th>Function:</th>
+ <th>Subject:</th>
+ <th>Last Update:</th>
+ <th> </th>
+ </tr>';
+
+if (is_array($data)) {
+ foreach ($data as $key => $val) {
+ $out .= '<tr>
+ <td><a href="edit_autoresponse.phtml?id='.$val["id"].'">[Edit]</a>
+ <a href="view_newsletter.phtml?id='.$val["id"].'">[View]</a></td>
+ <td>'.$val["subject"].'</td>
+ <td>'.$val["last_update"].'</td>
+ <td><a href="update_autoresponse.phtml?Command=Delete&id='.$val["id"].'" onClick="return(confirm(\'This will delete the Email Newsletter!\n\nAre you sure?\'))">[Delete]</a></td>
+ </tr>';
+ }
+}
+$out .= '</table>';
+echo $out;
+GLM_TOOLBOX::footer();
+?>
--- /dev/null
+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('<OPTION VALUE="',href,'">',text,'<\/OPTION>');
+}
--- /dev/null
+<HTML>
+<HEAD>
+<TITLE>Help</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" BACKGROUND="../../help/helpbg.gif" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">
+<FONT FACE="ms sans serif,arial,helvetica" SIZE=2 COLOR="#444444">
+<H4 align="center">Contact Help</H4>
+<hr>
+<?
+switch ($key) {
+ case "search":
+ ?>
+<h4 align="center">Contact Database Search</h4>
+
+<P>
+In this page you will start to build your query to the contact database.
+</p>
+<p>
+<big><b>Search:</b></big>
+</p>
+<p>
+<b>Search records for:</b>
+</p>
+<p>Here is where you will enter any keywords to use in the search. You must
+enter in something in the "Search records for" box. You may use more than one
+word (ie.) Sam Field.</p>
+<p><font color=red>HINT:</font>To help search use wildcards!</p>
+<p>? optional space<br>
+* optional spaces<br>
++ at least one space
+. will match anything<br>
+</p>
+<p><font color=green>NOTE:</font>Leaving this fields blank will select all
+contacts. You can leave this blank and choose "Mail OK" true to get all
+contacts that allow emails.</p>
+<p><b>Search Where in fields:</b></p>
+<p>Tells the database to Search "Anywhere", "Beginning", or "Ending" of the
+fields to be searched.</p>
+<p><b>In Fields:</b></p>
+<p>Select from "In Fields" box. This determines what fields to look in for
+this search.</p>
+<p><font color=red>HINT</font>
+If you want to select more than one field to search in hold down the 'Ctrl' key while clicking on the selection to select or
+deselect it from the list.</p>
+<p><font color=red>HINT</font>
+You can use the "All" and "None" buttons to help you save time. This will
+select all or none of the fields in the boxes.</p>
+<p><b>Search Type:</b></p>
+<p>Select the type of search you want (ie.) an "Exact string" search will return
+only those fields which match the "Search records" for string exactly as compared
+to "Or" which will return any field that match any words you place into "Search
+records for"</p>
+<p><b>Case Sensitivity:</b></p>
+<p>This will turn "On" and "Off" the case sensitivity.
+(ie.)If you leave it "Off" and enter "bob" it will return anything like
+"bob","BOB","Bob","BOb","boB",or "BoB" turned "On" will match only "bob".</p>
+
+<p>
+<big><b>Output of records</b></big>
+</p>
+<p><b>Output Fields:</b></p>
+<p>Select from "Output Fields" box. This determines what fields will be in the
+output of this search.</p>
+<p><font color=red>HINT</font>
+You can use the "All" and "None" buttons to help you save time. This will
+select all or none of the fields in the boxes.</p>
+<p><font color=red>HINT</font>
+If you want to select more than
+one Output field hold down the 'Ctrl' key while clicking on the selection to select or
+deselect it from the list.</p>
+<p><b>File Output:</b></p>
+<p>Select from here if you wish to download a file with the results of this
+search. The file will built "On the Fly" so you can download it.</p>
+<p><font color=green>NOTE:</font>The text file is output as report.doc. This
+is only a text file.
+</p>
+<p><b>Delimiter:</b></p>
+<p>This determines what separates the fields in your file.</p>
+
+<?
+ break;
+
+ case "List":
+ ?>
+<h4 align="center">List Contacts</h4>
+<P>
+This page is for listing the results of your query. You can download files if
+you have selected a file type or edit and delete the contact found.
+</p>
+<p><b>[Edit]</b></p>
+<p>Link to contact edit page.</p>
+
+<p><b>[Delete]</b></p>
+<p>Link to Delete Contact.</p>
+
+<p><big><b>Download Files</b></big></p>
+<p>If you see this then there is a file you can download.
+Click on the file and you can download it.</p>
+<?
+ break;
+
+ case "Edit":
+ ?>
+<h4 align="center">Edit a Contact</h4>
+<P>
+This page is for editing and modifying an existing Contact in the database.
+When editing is complete, click on the "Submit Query" button. The database will
+be updated, and you will be directed back to the "List Contacts" page.
+</p>
+<p>
+
+<p>
+<b>Submit Query</b>
+</p>
+<p>When you have made the changes you want to the Contact,
+you can click "Submit Query." This will update the information about the
+Contact in the database.
+</p>
+<?
+ break;
+
+ case "Add":
+ ?>
+<h4 align="center">Add an Contact</h4>
+<P>
+This page is for Adding Contacts in the database.
+When form is complete, click on the "Submit Query" button. The database will
+be updated, and you will be directed back to the "List Contacts" page.
+</p>
+
+<p>
+<b>Submit Query</b>
+</p>
+<p>When you have made the changes you want to the Contact,
+you can click "Submit Query." This will update the information about the
+Contact in the database.
+</p>
+<?
+ break;
+
+}
+?>
+<BR CLEAR=ALL>
+<CENTER><A HREF="" onClick = "window.close('self');"><IMG SRC="../../help/closewindow.gif" border=0></A></CENTER>
+</BODY>
+</HTML>
--- /dev/null
+.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; }
--- /dev/null
+<?php
+session_start();
+require_once "../../setup.phtml";
+require_once "contact_setup.inc";
+error_reporting();
+if (isset($mailout)) {
+ unset($_SESSION['mailout']);
+ //session_unregister("mailout");
+}
+if (isset($_SESSION['sess_vars'])) {
+ extract($_SESSION['sess_vars']);
+ unset($_SESSION['sess_vars']);
+ //session_unregister("sess_vars");
+}
+$qs = "SELECT count(*) as total
+ FROM ".TABLE;
+if (TABLE == CUSTOMER_TABLE) {
+ $qs .= " WHERE (fname != '-Guest-' OR fname is null)";
+}
+$res = $DB->db_auto_get_data($qs);
+$total = $res[0]['total'];
+GLM_TOOLBOX::top("Contact Database","help/contact.phtml?key=search","SteveContactsDatabase_1.0");
+GLM_TOOLBOX::html_nav_table($nav,$navWidth);
+?>
+<table id="admin-list-table">
+ <tr>
+ <td colspan=4>
+ There
+ <?php
+ if ($total < 1 ) {
+ echo " No records";
+ } elseif ($total > 1) {
+ echo "are $total contacts";
+ } else {
+ echo "is $total contact";
+ }
+ ?> in the database.
+ </td>
+ </tr>
+ <tr>
+ <th colspan=4 class="theader">
+ Search:
+ </th>
+ </tr>
+ <tr>
+ <td colspan=4>
+ <b>Search records for:</b><br>
+ </td>
+ </tr>
+ <tr>
+ <td colspan=4>
+ <form name="search" action="query_contact.phtml" method="POST" onSubmit="
+ var msg = '';
+ var errors = '';
+ var ping = 0;
+ var all = 0;
+ this.fvalue.value = '';
+ this.rfvalue.value = '';
+ this.rdvalue.value = '';
+
+ if(this.search.value == '') {
+ all++;
+ }
+
+ for(var i = 0;i<4;i++) {
+ if(this.search_type.options[i].selected){
+ ping++;
+ }
+ }
+
+ if(all == 0) {
+ if(ping == 0) {
+ errors += '-You must select a search type\n';
+ }
+ }
+
+ for(var i=0;i<<?php echo count($fields)?>;i++) {
+ if(this.ifields.options[i].selected) {
+ this.fvalue.value += ':' + this.ifields.options[i].value;
+ }
+ }
+
+ for(var i=0;i<<?php echo count($fields)?>;i++) {
+ if(this.return_fields.options[i].selected) {
+ this.rfvalue.value += ':' + this.return_fields.options[i].value;
+ }
+ }
+
+ for(var i=0;i<1;i++) {
+ if(this.dates.options[i].selected) {
+ this.rdvalue.value += ':' + this.dates.options[i].value;
+ }
+ }
+
+ if(all == 0) {
+ if(this.fvalue.value == '') {
+ errors += '-You must select at least one field to search in\n';
+ }
+ }
+
+ if(this.rfvalue.value == '') {
+ errors += '-You must select at least one field for output\n';
+ }
+
+ if(all == 1) {
+ if(errors == '') {
+ return(true);
+ }
+ }
+
+ if(errors == '') {
+ return(true);
+ } else {
+ msg += '_______________________________________\n\n';
+ msg += 'The form was not submitted please check\n';
+ msg += 'the following and resubmit\n\n';
+ msg += errors + '\n\n';
+ msg += '_______________________________________\n\n';
+
+ alert(msg);
+ return(false);
+ }
+ ">
+ <input name="search" value="<?php echo stripslashes($search)?>" size=40>
+ <input type="submit" name="Submit Query">
+ </td>
+ </tr>
+ <tr>
+ <th colspan=4 class="theader">
+ Search Dates Ranges
+ </th>
+ </tr>
+ <tr>
+ <td align="left" colspan=4 nowrap>
+ <div style="float:left;width:240px;height:35px;">Created From:<br> <?php echo $c_date_from?></div>
+ <div style="float:left;width:240px;height:35px;">Created To:<br> <?php echo $c_date_to?></div>
+ </td>
+ </tr>
+ <tr>
+ <td class="small" valign=top>
+ <b>In Fields:</b><br>
+ <select name="ifields" multiple size=8>
+ <?php foreach($fields as $key2=>$value2) {?>
+ <option value="<?php echo $key2?>" <?php echo (strstr($fvalue,$key2))?"selected":""?>><?php echo $value2?>
+ <?php }?>
+ </select>
+ <br>
+ <label for="in-all"><input type="radio" id="in-all" name="a" onClick="
+ for(var i=0;i<<?php echo count($fields)?>;i++) {
+ this.form.ifields.options[i].selected=1;
+ }
+ ">All</label>
+ <label for="in-none"><input type="radio" id="in-none" name="a" onClick="
+ for(var i=0;i<<?php echo count($fields)?>;i++) {
+ this.form.ifields.options[i].selected=0;
+ }
+ ">None</label>
+ </td>
+ <td valign=top class="small" nowrap>
+ <b>Search Where:</b><br>
+ <select name="alter">
+ <option value="0" <?php echo ($alter=="0")?"selected":""?>>Anywhere
+ <option value="1" <?php echo ($alter=="1")?"selected":""?>>Begining
+ <option value="2" <?php echo ($alter=="2")?"selected":""?>>Ending
+ </select><br>
+ <input type="hidden" name="fvalue">
+ <?php
+ if (is_array($boolean)) {
+ foreach ($boolean as $bool_key => $bool_val) {
+ echo '<br>
+ <b>'.$bool_val.'</b><br>';
+ echo search_bool($bool_key, ${$bool_key});
+ }
+ }
+ if (is_array($dropdowns)) {
+ foreach ($dropdowns as $drop_key => $drop_row) {
+ echo '<br>
+ <b>'.$drop_row['title'].'</b>';
+ echo '<br>';
+ if( is_array( $drop_row['drop'] ) ) {
+ echo GLM_TOOLBOX::build_picklist( $drop_key.'[]', $drop_row['drop'], ${$drop_key}, 'multiple', 0, null, 5 );
+ }
+ }
+ }
+ echo '</td><td valign=top width=25%>';
+?>
+ <br><b>Search Type:</b><br>
+ <select name="search_type" size=4>
+ <option value="1" <?php echo (!isset($search_type) || $search_type=="1")?"selected":""?>>Exact string
+ <option value="2" <?php echo ($search_type=="2")?"selected":""?>>And
+ <option value="3" <?php echo ($search_type=="3")?"selected":""?>>Or
+ <option value="4" <?php echo ($search_type=="4")?"selected":""?>>Not
+ </select>
+ </td>
+ <td valign=top class=small width=25%>
+ <b>Case Sensitivity:</b><br>
+ <select name="case">
+ <option value="ON" <?php echo ($case == "ON")?"selected":""?>>On
+ <option value="OFF" <?php echo (!isset($case) || $case == "OFF")?"selected":""?>>Off
+ </select><br>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="4">
+<?php
+ $sql = "
+ SELECT contact_inq.*, inq_group.name as group
+ FROM contact_inq
+ LEFT OUTER JOIN inq_group
+ ON (contact_inq.groupid = inq_group.id)
+ WHERE inq_group.id != 6
+ ORDER BY groupid, pos";
+
+ $interests = array();
+ $intData = $DB->db_auto_get_data($sql);
+ foreach ($intData as $row) {
+ $interests[$row['group']][$row['id']] = $row['header'];
+ }
+
+ foreach ($interests as $i => $j) {
+ echo '<fieldset>';
+ echo '<legend>';
+ echo $i;
+ echo '</legend>';
+ foreach ($j as $k => $v) {
+ echo '<label class="glmCheckBox">';
+ echo '<input type="checkbox" name="cols[]" value="'.$k.'" ';
+ if ( is_array($cols)
+ && in_array($data['id'], $cols)) {
+ echo " checked";
+ }
+ echo '>';
+ echo $v;
+ echo '</label>';
+ }
+ echo '</fieldset>';
+ }
+?>
+ </td>
+ </tr>
+ <tr>
+ <th colspan=4>
+ Output of records:
+ </th>
+ </tr>
+ <tr>
+ <td class="small" valign=top>
+ <b>Output Fields:</b><br>
+ <select name="return_fields" multiple size=8>
+ <?php foreach($fields as $key2=>$value2) {?>
+ <option value="<?php echo $key2?>" <?php echo (strstr($rfvalue,$key2))?"selected":""?>><?php echo $value2?>
+ <?php }?>
+ </select>
+ <br>
+ <input type="hidden" name="rfvalue">
+ <label for="out-all"><input type="radio" id="out-all" name="a" onClick="
+ for(var i=0;i<<?php echo count($fields)?>;i++) {
+ this.form.return_fields.options[i].selected=1;
+ }
+ for(var i=0;i<<?php echo ($p_date_from)?"3":"1";?>;i++) {
+ this.form.dates.options[i].selected=1;
+ }
+ ">All</label>
+ <label for="out-none"><input id="out-none" type="radio" name="a" onClick="
+ for(var i=0;i<<?php echo count($fields)?>;i++) {
+ this.form.return_fields.options[i].selected=0;
+ }
+ for(var i=0;i<<?php echo ($p_date_from)?"3":"1";?>;i++) {
+ this.form.dates.options[i].selected=0;
+ }
+ ">None</label>
+ </td>
+ <td class="small" valign=top>
+ <input type="hidden" name="rdvalue" value="">
+ <b>Output fields (Dates):</b>
+ <select name="dates" multiple size=3>
+ <option value="create_date" <?php echo (strstr($dates,"create_date"))?"selected":""?>>Created Date
+ <?php if($p_date_from)
+ {?>
+ <option value="purch_date" <?php echo (strstr($dates,"purch_date"))?"selected":""?>>Last Purchase Date
+ <?php }
+ if($a_date_from)
+ {?>
+ <option value="access_date" <?php echo (strstr($dates,"access_date"))?"selected":""?>>Last Access Date
+ <?php }?>
+ </select>
+ </td>
+ <td class="small" valign=top width=25%>
+ <b>File output:</b><br>
+ <select name="file" size=4>
+ <option value="" <?php echo (!isset($file) || $file == "")?"selected":""?>>No File
+ <option value="zip" <?php echo ($file=="zip")?"selected":""?>>zip file
+ <option value="gz" <?php echo ($file=="gz")?"selected":""?>>tar.gz(tar ball)
+ <option value="rpt" <?php echo ($file=="rpt")?"selected":""?>>text file
+ </select>
+ </td>
+ <td valign=top class=small width=25%>
+ <b>Delimiter:</b><br>
+ <select name="delimiter" size=4>
+ <option value="tab" <?php echo ($delimiter=="tab")?"selected":""?>>TAB
+ <option value="comma" <?php echo ($delimiter=="comma")?"selected":""?>>Comma
+ <option value="csv" <?php echo ($delimiter=="csv")?"selected":""?>>CSV
+ <option value="pipe" <?php echo ($delimiter=="pipe")?"selected":""?>>Pipe
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="4" align="center">
+ <input type="submit" name="Submit Query">
+ </td>
+ </tr>
+ </table>
+<?php
+GLM_TOOLBOX::footer();
+?>
--- /dev/null
+<?php
+require_once '../../setup.phtml';
+require_once 'contact_setup.inc';
+if (!$start) {
+ $start = 0;
+}
+
+if ($postquery) {
+ $query_string = $postquery;
+}
+$checkqs = "SELECT count(*) as contacts
+ FROM ".TABLE;
+
+if (!$checkres = $DB->db_auto_get_data($checkqs)) {
+ GLM_TOOLBOX::html_error(DB_ERROR_MSG.__LINE__.$checkqs,1);
+}
+
+$numcontacts = $checkres[0]['contacts'];
+if ($numcontacts == 0) {
+ GLM_TOOLBOX::html_error("There are no contacts in the database",1);
+}
+//var_dump($query_string);
+//var_dump($_REQUEST);
+//exit;
+if(!isset($back) && !isset($query_string) && !isset($query_no)) {
+ $query = "SELECT ".ID.",*
+ FROM ".TABLE."
+ WHERE ".WHERE."
+ ORDER BY lname,fname";
+
+ $query = addslashes($query);
+ $qs = "SELECT id
+ FROM query_db
+ WHERE query_name = '(current)'";
+
+ if (!$res = $DB->db_exec($qs)) {
+ GLM_TOOLBOX::html_error(DB_ERROR_MSG.__LINE__.$qs,1);
+ }
+
+ if ($DB->db_numrows($res)==0) {
+ $qs = "INSERT
+ INTO query_db
+ (query,query_name)
+ VALUES ('$query','(current)')";
+ } else {
+ $id = $res->fetchColumn();
+ $qs = "UPDATE query_db
+ SET query = '$query',
+ file = '',
+ delimiter = ''
+ WHERE id = $id";
+ }
+ if (!$res = $DB->db_exec($qs)) {
+ html_error(DB_ERROR_MSG.__LINE__.$qs,1);
+ }
+ unset($qs);
+}
+
+if ($delimiter == "csv") {
+ $csv = TRUE;
+}
+
+if (isset($query_string) && $query_string) {
+ $query_string = strtr($query_string,"\n"," ");
+ $query_string = strtr($query_string,"\t"," ");
+ $query_string = stripslashes($query_string);
+ $qs = $query_string;
+} elseif ($query_no) {
+ $qs = "select query from query_db where id = $query_no";
+ $queryres = $DB->db_exec($qs);
+ if ($queryres->rowCount() == 0) {
+ $qs = "SELECT ".ID.",*
+ FROM ".TABLE."
+ WHERE ".WHERE."
+ ORDER BY lname,fname";
+ } else {
+ $qs = $queryres->fetchColumn();
+ }
+} else {
+ $queryqs = "SELECT query
+ FROM query_db
+ WHERE query_name LIKE '(current)'";
+ $queryres = $DB->db_exec($queryqs);
+ if ($queryres->rowCount() == 0) {
+ $qs = "SELECT ".ID.",*
+ FROM ".TABLE."
+ WHERE ".WHERE."
+ ORDER BY lname,fname";
+ } else {
+ $qs = $queryres->fetchColumn();
+ }
+}
+
+GLM_TOOLBOX::top("List Contacts","help/contact.phtml?key=List");
+?>
+<script src="wm.js"></script>
+<script src="msg.js"></script>
+<table id="admin-list-table">
+<?php
+GLM_TOOLBOX::html_nav_table($nav,$navWidth);
+if (NEWSLETTER) {
+$mquery = "select id,subject,last_update from news_response order by last_update desc;";
+ $mres = $DB->db_exec($mquery);
+ $mailout = array();
+ while ($mrow = $mres->fetch())
+ {
+ $mailout[] = $mrow;
+ }
+?>
+<script type="text/javascript">
+ var remind;
+ remind = 'This will mailout the Newsletter\n';
+</script>
+<table id="admin-edit-table" style="width:500px;">
+ <tr>
+ <th colspan=2>
+ <form action="mailout.phtml" method="POST" onSubmit="return(confirm(remind));">
+ <select name="mail_id" style="width:100%;"><?php
+ unset($mrow);
+ foreach ($mailout as $mrow) {
+ echo '<option value="'.$mrow["id"].'">';
+ echo ' '.htmlspecialchars(strip_tags($mrow["subject"]));
+ echo ' (Updated: '.$mrow["last_update"].')';
+ echo '</option>';
+ }
+ ?>
+ </select>
+ <input type="hidden" name="postmail" value="<?php echo $qs?>">
+ <input type="submit" value="Mail Out the Newsletter">
+ </form>
+ </th>
+</tr>
+<?php }
+$totalqs = substr_replace($qs," count(*) as total FROM ",strpos($qs,"SELECT")+7,strpos($qs,"FROM")-3);
+if (strpos($totalqs,"ORDER BY")!=0) {
+ $totalqs = substr_replace($totalqs,"",strpos($totalqs,"ORDER"));
+}
+if (!$totalres = $DB->db_exec($totalqs)) {
+ GLM_TOOLBOX::html_error(DB_ERROR_MSG.__LINE__.$totalqs,1);
+}
+if ($totalres->rowCount() == 0) {
+ $totalnum = 0;
+} else {
+ $totalnum = $totalres->fetchColumn();
+}
+$qs .= " LIMIT ".ENTRIES_PER_PAGE." OFFSET ".$start;
+$res = $DB->db_exec($qs);
+?>
+<tr>
+ <td colspan="2"><?php echo $totalnum?>Result(s)
+<?php
+if ($_REQUEST['Action']) {
+ echo '<div style="background-color:green;color:white;padding:5px;">'.$_REQUEST['Action'].' Successfully!</div>';
+}
+?></td>
+</tr>
+<?php
+if(!$res) GLM_TOOLBOX::html_error(DB_ERROR_MSG.__LINE__.$qs,1);
+// What page are you on?
+if ($start==0) {
+ $page == 1;
+} else {
+ $page = ($start / ENTRIES_PER_PAGE) + 1;
+}
+$totalpages = floor($totalnum / ENTRIES_PER_PAGE);
+$totalpages++;
+
+$result_string = "";
+$num = $DB->db_numrows($res);
+if (!$start) {
+ $start = 0;
+}
+$begin = 0;
+$ending = $num;
+
+$stuff = "query_string=".urlencode($query_string)."&file=".$file."&delimiter=".$delimiter."&csv=".$csv;
+// for paging results get a first page and last page link also
+// first page is easy use 0
+$first = "<a href=\"list_contact.phtml?".$stuff."&start=0\">FIRST</a> - ";
+// last page use total pages
+$lastpage = " - <a href=\"list_contact.phtml?".$stuff."&start=".( ( $totalpages - 1 ) * ENTRIES_PER_PAGE )."\">Last</a>";
+if ($totalnum > ENTRIES_PER_PAGE && ( $page != $totalpages ) ) {
+ $end = ENTRIES_PER_PAGE + $start;
+} else {
+ $end = $totalnum;
+}
+$last = $start - ENTRIES_PER_PAGE;
+if (!$query_string) {
+ $query_string = $qs;
+ $query_string = str_replace(" LIMIT ".ENTRIES_PER_PAGE." OFFSET ".$start,"",$query_string);
+}
+
+if (($start - ENTRIES_PER_PAGE) < 0) {
+ $prev = "PREV";
+} else {
+ $prev = "<a href=\"list_contact.phtml?".$stuff."&start=".$last."\">PREV</a>";
+}
+if ($end < $totalnum) {
+ $next = "<a href=\"list_contact.phtml?".$stuff."&start=".$end."\">NEXT</a>";
+} else {
+ $next = "NEXT";
+}
+?>
+<tr>
+ <td colspan="2">
+ <?php
+ if($num!=0)
+ echo $first.$prev."-".($start+1)."-to-".$end."-".$next.$lastpage;
+ ?>
+ </td>
+</tr>
+<tr>
+ <td colspan="2">
+<?php
+if (count($res)>0) {
+ for ($i=$begin;$i<$ending;$i++) {
+ if (!$row = $DB->db_fetch_array($res,$i,PGSQL_ASSOC)) {
+ GLM_TOOLBOX::html_error(DB_ERROR_MSG.__LINE__,1);;
+ }
+ $col = 0;
+ foreach ($row as $fieldName => $fieldVal) {
+ $fields[$col] = $fieldName;
+ if ($i == $begin) {
+ $head_ar[] = $fieldName;
+ }
+ $body_ar[] = $fieldVal;
+ ++$col;
+ }
+ if ($i == $begin) {
+ $head_array = array_values($head_ar);
+ }
+ $contact_data[] = array_values($body_ar);
+ ?>
+ <tr <?php echo $background;
+ $id = ID;
+ ?>>
+ <td nowrap><a href="edit_contact.php?<?php echo ID . '=' . $row[$id]?>&start=<?php echo $start;?>">
+ [Edit]</a>
+ <a href="update_contact.phtml?Command=Delete&id=<?php echo $row[$id]?>&start=<?php echo $start;?>" onClick="
+ if(confirm('This will delete this record Are you sure?')) {
+ return(true);
+ }else {
+ return(false);
+ }
+ ">
+ [Delete]</a>
+ </td>
+ <td align=left>
+ <?php
+ foreach($fields as $key) {
+ if($key != "id" && $key != "cust_id"
+ && $key != "userid" && $key != "usernum"
+ && $key != "usergroup" && $key != "passwd")
+ echo $row[$key]." ";
+ }
+ ?>
+ </td>
+ </tr>
+ <?php
+ }
+}
+ ?>
+ </td>
+</tr>
+ </table>
+ <?php
+if(isset($file) && $file != "" && $DB->db_numrows($res) > 0) {
+?>
+<table>
+<tr>
+ <th colspan=2>Download files</th>
+</tr>
+<tr>
+ <td><form action="download.phtml">
+ <input type="hidden" name="query_string" value="<?php echo $query_string?>">
+ <input type="hidden" name="file" value="<?php echo $file?>">
+ <input type="hidden" name="delimiter" value="<?php echo $delimiter?>">
+ <input type="hidden" name="csv" value="<?php echo $csv?>">
+ <input type="submit" value="Download Report">
+ </form></td>
+</tr>
+</table>
+<?php
+}
+GLM_TOOLBOX::html_nav_table($nav,5);
+GLM_TOOLBOX::footer();
+?>
--- /dev/null
+<?php
+include_once '../../setup.phtml';
+include "contact_setup.inc";
+GLM_TOOLBOX::top('Contact Inquiries', '');
+// Adjust the nav for this page, add the Edit Groups page.
+if (is_array($nav) && array_key_exists('Contact Inquiry Fields', $nav))
+{
+ $tmp = array('Inquiry Groups' => 'list_groups.php');
+ array_insert($nav, 'Contact Inquiry Fields', $tmp);
+}
+GLM_TOOLBOX::html_nav_table($nav, $navWidth);
+$qs = "
+ SELECT id, name
+ FROM inq_group
+ ORDER BY name;";
+$result = $DB->db_exec( $qs );
+?>
+<table id="admin-list-table">
+ <tr>
+ <th colspan="2">
+ <form action="edit_group.php" method="POST" name="edit_group">
+ <input type="submit" name="Command" value="Add Group" />
+ </form>
+ </th>
+ <tr>
+ <tr>
+ <th>Options:</th>
+ <th>Group:</th>
+ <tr>
+ <?php
+ if($DB->db_numrows($result) > 0)
+ {
+ for($i=0 ;$i < $DB->db_numrows($result); $i++)
+ {
+ $data = $DB->db_fetch_array($result, $i, PGSQL_ASSOC);
+ ?>
+ <tr>
+ <td width="10" nowrap><a href="edit_group.php?id=<?php echo $data['id'];?>&Command=Edit">[Edit / Delete]</a></td>
+ <td width="80%" align="left"><?php echo $data['name'];?>
+ </tr>
+ <?php
+ }
+ }
+ else
+ {
+ ?>
+ <tr>
+ <th colspan="2">Nothing in the database yet</th>
+ </tr>
+ <?php
+ }
+ ?>
+</table>
+<?php
+GLM_TOOLBOX::footer();
+?>
--- /dev/null
+<?php
+require_once '../../setup.phtml';
+require_once 'contact_setup.inc';
+
+GLM_TOOLBOX::top("Query DB","");
+
+GLM_TOOLBOX::html_nav_table($nav,$navWidth);
+?>
+<script src="<?php echo MEDIA_BASE_URL."admin/wm.js"?>"></script>
+<script src="<?php echo MEDIA_BASE_URL."admin/msg.js"?>"></script>
+<table id="admin-list-table">
+<tr bgcolor="#2f4f4f">
+ <th class="theader">
+ Functions:
+ </th>
+ <th class="theader">
+ Queries in database
+ </th>
+</tr>
+<?php
+//if(!$dbd = db_connect()) html_error(DB_ERROR_MSG,0);
+
+$qs = "SELECT id,query_name
+ FROM query_db";
+
+if(!$res = $DB->db_exec($qs)) GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs,0);
+
+for($i=0;$i<$DB->db_numrows($res);$i++) {
+ $row = $DB->db_fetch_array($res,$i,PGSQL_ASSOC);
+
+?>
+ <script lang="javascript">
+ var o<?php echo $i?> = new Object();
+ o<?php echo $i?>.msg = 'You are about to Permanently Delete this Query';
+ o<?php echo $i?>.url = 'del_query.phtml?id=<?php echo $row[id]?>';
+ o<?php echo $i?>.popup = '1';
+ o<?php echo $i?>.popup.name = "delwin";
+ o<?php echo $i?>.width = 630;
+ o<?php echo $i?>.height = 300;
+ </script>
+<tr>
+ <td>
+ <a href="query_contact.phtml?query_no=<?php echo $row[id]?>">[Recall]</a>
+ <?php if($row[query_name] != "(current)") {?>
+ <a href="del_query.phtml?id=<?php echo $row[id]?>" onClick="
+ glm_confirm(o<?php echo $i?>);
+ return(false);
+ ">[Delete]</a>
+ <?php }?>
+ </td>
+ <td><b><?php echo $row[query_name]?></b></td>
+</tr>
+<?php }?>
+</table>
+<?php
+GLM_TOOLBOX::footer();
+?>
--- /dev/null
+<html>
+<head>
+<title>Mailing out The Newsletter</title>
+</head>
+<body bgcolor="white">
+<?php
+require_once '../../setup.phtml';
+require_once 'contact_setup.inc';
+
+// File names for SPAMerizer
+$Filename = tempnam( "/var/spool/SPAMerizer", "MOUNP" );
+unlink($Filename);
+
+$HeadFilename = $Filename.".head";
+$BodyFilename = $Filename.".body";
+$ToFilename = $Filename.".to";
+$ReadyFilename = $Filename.".ready";
+
+$postmail = stripslashes($postmail);
+
+$pattern = '/SELECT.*FROM/is';
+$replace = "SELECT email INTO TEMPORARY temp_table FROM";
+$postmail = preg_replace($pattern, $replace, $postmail);
+$postmail = preg_replace("/ORDER BY.*/is","", $postmail);
+$postmail .= " AND ".MAILOK;
+
+if (!$mailres = $DB->db_exec($postmail)) {
+ html_error(DB_ERROR_MSG.__LINE__.$postmail, 1);
+}
+
+$mailqs = "SELECT
+ DISTINCT ON (email) email
+ FROM temp_table
+ GROUP BY email;";
+flush();
+if (!$mailres = $DB->db_exec($mailqs)) {
+ html_error(DB_ERROR_MSG.__LINE__.$mailqs, 1);
+}
+
+if ($DB->db_numrows($mailres)>0) {
+ for($a=0;$a<$DB->db_numrows($mailres);$a++) {
+ $mvdata = $DB->db_fetch_array($mailres, $a, PGSQL_ASSOC);
+ $email = trim($mvdata["email"]);
+ if ($email) {
+ $mail[] = $email;
+ }
+ }
+}
+if (is_array($mail) && count($mail)>0) {
+ // write the temp.to file
+ $mail = implode("\n", $mail);
+ $fp = fopen($ToFilename, "w");
+ fputs($fp, $mail, strlen($mail));
+ fclose($fp);
+} else {
+ $mail = "";
+}
+
+
+if ($mail != "") {
+ // I am changing this to a two part mime type email
+ // html and text
+ // using class_html
+ $responseqs = "SELECT *
+ FROM news_response
+ WHERE id = $mail_id";
+ if (!$resres = $DB->db_exec($responseqs)) {
+ html_error(DB_ERROR_MSG.$responseqs, 0);
+ }
+
+ $responserow = $DB->db_fetch_array($resres, 0, PGSQL_ASSOC);
+
+ $subject = trim($responserow['subject']);
+ $data['subject'] = &$subject;
+ $message = $responserow['response'];
+ // html part of email
+ //$data['response'] = stripslashes(nl2br($message));
+ $data['response'] = $message;
+ $data['url'] = MEDIA_BASE_URL;
+
+ $html = explode_template(NEWSLETTER_PROTOTYPE,$data);
+
+ // text part of email
+ $text = strip_tags($message);
+ $text .= "\n\n-------------------------------------------------------------------\n";
+ $text .= "You are receiving this message because you have expressed an interest in\n";
+ $text .= "receiving specials and information from ".SITENAME.". If you do not\n";
+ $text .= "wish to receive future items of this nature, please reply to this e-mail\n";
+ $text .= "with the word \"CANCEL\" on the subject line. You will then be removed \n";
+ $text .= "from future mailings.\n";
+ $text .= "-------------------------------------------------------------------\n";
+
+ // Write the temp.header file
+ $glm_headers = "NotifyAddr: ".OWNER_EMAIL."\n"
+ . "ProcessName: ".SITENAME."\n"
+ . "From: ".FROM_NEWS_EMAIL."\n"
+ . "ReportInterval: 2\n"
+ . "BlockSize: 1\n"
+ . "ProductionMode: ".PRODUCTION_MODE."\n";
+
+ $fp = fopen($HeadFilename, "w");
+ fputs($fp, $glm_headers, strlen($glm_headers));
+ fclose($fp);
+
+ $headers = "From: ".FROM_NEWS_EMAIL."\n".
+ "To: ".OWNER_EMAIL."\n".
+ "Subject: $subject\n".
+ "Reply-to: ".REPLY_TO."\n".
+ "Mime-Version: 1.0\n".
+ "Content-Type: multipart/alternative; boundary=ContentBoundry\n\n";
+ $fp = fopen($BodyFilename,"w");
+ if(HTML_EMAIL=="ON"){
+ $body_html = '--ContentBoundry
+Content-Type: text/plain; charset="UTF-8"
+'.$text.'
+--ContentBoundry
+Content-Type: text/html; charset="UTF-8"
+
+'.$html.'
+
+--ContentBoundry--';
+ fputs($fp, $headers, strlen($headers));
+ fputs($fp, $body_html, strlen($body_html));
+ } else {
+ fputs($fp, $headers, strlen($headers));
+ fputs($fp, $text, strlen($text));
+ }
+ fclose($fp);
+ // write the temp.ready file and your done!
+ $fp = fopen($ReadyFilename, "w");
+ fclose($fp);
+?>
+<table>
+<tr>
+ <td>Mail the current <?php echo $subject?></td>
+</tr>
+<tr>
+ <td><?php echo (PRODUCTION_MODE == "ON")?"ProductionMode is ON, Mail is sent.":"ProductionMode is OFF, Mail is not sent."?></td>
+</tr>
+<tr>
+ <td><?php echo (HTML_EMAIL == "ON")?"HTML Email is ON, Mail is html encoded.":"HTML Email is OFF, Mail is plain text."?></td>
+</tr>
+<tr>
+ <td>You will recieve notification on the mailing task by email at <?php echo OWNER_EMAIL?>.</td>
+</tr>
+</table>
+<?php
+} else {
+?>
+<table width=500 bgcolor="#e0e0e0">
+<tr bgcolor="#2f4f4f">
+ <th><font color=white>Newsletter Not Sent!</th>
+ </tr>
+</table>
+<?php
+}
+
+?>
+</body>
+</html>
--- /dev/null
+body {
+ background-color: #FFFFFF;
+}
+
+.navlink {
+ font-size: 80%;
+ font-family: arial;
+}
+
+td {
+ font-size: 80%;
+ font-family: arial,helvetica;
+}
+
+.theader {
+ font-size: 120%;
+ font-family: arial,helvetica;
+ color: #FFFFFF;
+}
+
+.theadertd {
+ background-color: #000080;
+}
--- /dev/null
+function glm_confirm(o) {
+ var p = o.msg.split("\n");
+ var k = 0;
+ for(i = 0;i < p.length;i++) {
+ if(k > p[i].length)
+ continue;
+ else
+ k = p[i].length;
+ }
+
+ var bound = "";
+ for(i = 0; i < k; i++) {
+ bound = bound+'_';
+ }
+ var str = bound+"\n\n"+o.msg+"\n\n"+bound+"\n\nAre You Sure?";
+ if(confirm(str)) {
+ if(o.popup == '1') {
+ var nw = new Object();
+ nw.url = o.url;
+ nw.name = o.popup.name;
+ nw.width = o.width;
+ nw.height = o.height;
+ glm_open(nw);
+ }
+ else {
+ location.replace(o.url);
+ }
+ }
+}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
+</head>
+<body>
+<table cellspacing="0" cellpadding="0" border="0" width="100%">
+ <tr>
+ <td align="center">
+ <table cellspacing="0" cellpadding="0" border="0" width="550" bgcolor="#ffffff">
+ <tr>
+ <td>
+ <a href="<!-- url -->"><img src="<!-- url -->assets/nHeader.jpg" width="550" height="114" alt="" style="border: 0; display: block;"></a>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <table cellspacing="15" cellpadding="0" border="0">
+ <tr>
+ <td>
+ <font face="arial, helvetica, sans-serif" size="2">
+ <!-- response -->
+ </font>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <font face="arial, helvetica, sans-serif" size="1">
+ <hr>
+ <!-- bailout -->
+ </font>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+</body>
+</html>
--- /dev/null
+2002-05-07 13:47 matrix
+
+ * contact_setup.inc, del_query.phtml, download.phtml,
+ edit_contact.phtml, form.js, index.phtml, list_contact.phtml,
+ list_query.phtml, mailout.phtml, main.css, msg.js,
+ query_contact.phtml, query_db.phtml, query_save.phtml,
+ update_contact.phtml, verify.js, wm.js, help/contact.phtml,
+ notes/ChangeLog, notes/Contact, notes/adm2.sql, notes/contact.sql,
+ notes/guest.sql: "version 2.4"
+
+2002-05-07 13:45 matrix
+
+ * contact.sql, contact_setup.inc, edit_contact.phtml,
+ list_contact.phtml, update_contact.phtml, notes/ChangeLog,
+ notes/contact.sql, notes/Contact: adding ChangeLog file and moving
+ sql file into notes. I have also set the insert part of
+ update_contact.phtml to use nextval to generate the PRIMEKEY so
+ this will work with previous version of th shop which don't have
+ the default set on cust_id
+
+2002-05-07 11:14 matrix
+
+ * contact.sql, contact_setup.inc, del_query.phtml, download.phtml,
+ edit_contact.phtml, form.js, index.phtml, list_contact.phtml,
+ list_query.phtml, mailout.phtml, main.css, msg.js,
+ query_contact.phtml, query_db.phtml, query_save.phtml,
+ update_contact.phtml, verify.js, wm.js, help/contact.phtml,
+ notes/adm2.sql, notes/guest.sql: testing out both contact and
+ customer table use
+
+2002-05-07 10:08 matrix
+
+ * form.js, msg.js, verify.js, wm.js: "putting javascript files in
+ dir"
+
+2002-05-07 09:57 matrix
+
+ * index.phtml: "all versions now 2.0"
+
+2002-05-07 09:57 matrix
+
+ * index.phtml: new file
+
+2002-05-07 09:44 matrix
+
+ * admin_constants.inc, contact.phtml, contact.sql,
+ contact_setup.inc, contact_test.sql, del_query.phtml,
+ download.phtml, edit_contact.phtml, index.html, list_contact.phtml,
+ list_cust_form.phtml, list_customers.phtml, list_query.phtml,
+ mailout.phtml, main.css, path.phtml, query_contact.phtml,
+ query_db.phtml, query_save.phtml, shopping_cart_setup.inc,
+ update_contact.phtml, help/contact.phtml, notes/adm2.sql,
+ notes/guest.sql: "merging final changes into one app"
+
+2002-03-14 11:23 matrix
+
+ * download.phtml: removed offending dot
+
+2002-03-12 10:32 matrix
+
+ * contact_setup.inc: file contact_setup.inc was initially added on
+ branch glm-Contact-2-0.
+
+2002-03-12 10:32 matrix
+
+ * download.phtml: file download.phtml was initially added on branch
+ glm-Contact-2-0.
+
+2002-03-12 10:32 matrix
+
+ * contact.phtml, contact_setup.inc, del_query.phtml,
+ download.phtml, edit_contact.phtml, list_contact.phtml,
+ list_query.phtml, mailout.phtml, query_contact.phtml,
+ query_db.phtml, update_contact.phtml: make it customer and ocntact
+
+2002-03-12 09:36 matrix
+
+ * list_cust_form.phtml, list_customers.phtml, path.phtml,
+ shopping_cart_setup.inc: updates
+
+2002-03-12 09:34 matrix
+
+ * contact.phtml, del_query.phtml, edit_contact.phtml,
+ list_contact.phtml, list_query.phtml, query_contact.phtml,
+ query_db.phtml, update_contact.phtml: prepare for merging
+
+2001-12-17 10:13 matrix
+
+ * list_contact.phtml, mailout.phtml: added ID
+
+2001-12-17 10:02 matrix
+
+ * list_contact.phtml, mailout.phtml: mail can't be sent by url
+
+2001-11-27 16:50 matrix
+
+ * contact.phtml, del_query.phtml, edit_contact.phtml,
+ list_contact.phtml, list_query.phtml, query_contact.phtml,
+ query_db.phtml, query_save.phtml, update_contact.phtml: needed to
+ update adding contacts to customer table as there is no default
+ value for cust_id
+
+2001-11-21 14:07 matrix
+
+ * contact.phtml, del_query.phtml, edit_contact.phtml,
+ list_contact.phtml, list_query.phtml, path.phtml,
+ query_contact.phtml, query_db.phtml, update_contact.phtml: using
+ setup.phtml not path.phtml
+
+2001-11-07 14:30 matrix
+
+ * list_contact.phtml: removed echo
+
+2001-11-07 14:27 matrix
+
+ * contact.phtml, del_query.phtml, edit_contact.phtml,
+ list_query.phtml, mailout.phtml, path.phtml, query_contact.phtml,
+ query_db.phtml, update_contact.phtml: updatng now using setup.phtml
+
+2001-11-07 14:24 matrix
+
+ * list_contact.phtml: correcting email out code
+
+2001-10-15 15:19 matrix
+
+ * contact.phtml, query_contact.phtml: adding date search
+
+2001-10-11 14:44 matrix
+
+ * list_contact.phtml: updating
+
+2001-10-11 14:34 matrix
+
+ * mailout.phtml: file mailout.phtml was initially added on branch
+ glm-Contact-2-0.
+
+2001-10-11 14:32 matrix
+
+ * list_contact.phtml, mailout.phtml: added autoresponder
+
+2001-09-25 10:14 matrix
+
+ * path.phtml: changed the path so we use one file
+
+2001-09-25 10:13 matrix
+
+ * contact.phtml: tr tag
+
+2001-07-02 14:29 matrix
+
+ * path.phtml: symplified the path files now this referes to the
+ main one in admin
+
+2001-06-22 08:55 matrix
+
+ * contact.phtml, contact.sql, edit_contact.phtml,
+ update_contact.phtml: adding field referred_by
+
+2001-06-19 08:50 matrix
+
+ * list_contact.phtml: no real change
+
+2001-06-19 08:49 matrix
+
+ * update_contact.phtml, edit_contact.phtml: modified for mailok
+
+2001-06-19 08:45 matrix
+
+ * list_contact.phtml: modified for errors on recalls
+
+2001-06-19 08:45 matrix
+
+ * edit_contact.phtml, update_contact.phtml: modified for mailok
+
+2001-06-18 10:08 matrix
+
+ * query_db.phtml: shop_query_db
+
+2001-06-18 10:08 matrix
+
+ * help/helpbg.gif: file helpbg.gif was initially added on branch
+ glm-Contact-shop-1-0.
+
+2001-06-18 10:08 matrix
+
+ * help/: closewindow.gif, contact.phtml, helpbg.gif: added images
+ to help folder
+
+2001-06-18 10:08 matrix
+
+ * help/closewindow.gif: file closewindow.gif was initially added on
+ branch glm-Contact-shop-1-0.
+
+2001-06-18 10:05 matrix
+
+ * query_contact.phtml: shop_query_db
+
+2001-06-18 10:04 matrix
+
+ * list_query.phtml: added nav links
+
+2001-06-18 10:03 matrix
+
+ * list_query.phtml: new shop query db
+
+2001-06-11 13:14 matrix
+
+ * list_contact.phtml: error correction
+
+2001-06-11 10:51 matrix
+
+ * list_contact.phtml: if there are no queries insert current
+
+2001-06-11 10:31 matrix
+
+ * list_contact.phtml: if there are no contacts html_error
+
+2001-06-11 10:18 matrix
+
+ * list_query.phtml: added nav to top of page
+
+2001-06-11 10:15 matrix
+
+ * help/contact.phtml: corrected paths to help images
+
+2001-06-08 09:17 matrix
+
+ * contact.sql: changing query table name to keep from messing up
+ other application
+
+2001-06-08 09:16 matrix
+
+ * help/contact.phtml: updateing help file
+
+2001-06-08 09:12 matrix
+
+ * contact.phtml: changed radio buttons on mail_ok to drop down
+
+2001-06-08 08:50 matrix
+
+ * list_contact.phtml: modified
+
+2001-06-08 08:46 matrix
+
+ * contact.phtml: made the mail_ok a drop down
+
+2001-06-07 14:54 matrix
+
+ * contact.phtml, list_contact.phtml, query_contact.phtml: updated
+ per gloriebe contactdb
+
+2001-06-07 14:06 matrix
+
+ * query_contact.phtml, help/contact.phtml: made changes for ereg
+ wildcards
+
+2001-06-06 15:51 matrix
+
+ * contact.phtml, contact.sql, edit_contact.phtml,
+ list_contact.phtml, query_contact.phtml, query_save.phtml,
+ update_contact.phtml: shop version
+
+2001-06-06 15:42 matrix
+
+ * main.css: added file
+
+2001-06-06 15:40 matrix
+
+ * report.rpt: "removed"
+
+2001-06-06 15:00 matrix
+
+ * contact.phtml, list_contact.phtml, query_contact.phtml,
+ update_contact.phtml, help/contact.phtml: worked out some bugs
+
+2001-06-06 13:41 matrix
+
+ * help/contact.phtml: changed path on images
+
+2001-06-06 13:38 matrix
+
+ * main.css: adding needed files
+
+2001-06-06 13:38 matrix
+
+ * main.css: file main.css was initially added on branch
+ glm-Contact-2-0.
+
+2001-06-05 11:17 matrix
+
+ * path.phtml: changed path to help
+
+2001-06-05 11:13 matrix
+
+ * path.phtml: changed path to help
+
+2001-06-05 10:45 matrix
+
+ * path.phtml: added path file
+
+2001-06-05 10:38 matrix
+
+ * contact.phtml, list_contact.phtml, query_contact.phtml: added
+ pipe and csv delimiter
+
+2001-05-31 12:43 matrix
+
+ * contact.phtml, contact.sql, contact_test.sql, del_query.phtml,
+ edit_contact.phtml, list_contact.phtml, list_query.phtml,
+ query_contact.phtml, query_db.phtml, query_save.phtml,
+ update_contact.phtml, help/contact.phtml: combining the contact
+ databases
+
+2001-04-04 13:42 matrix
+
+ * admin_constants.inc, index.html, list_cust_form.phtml,
+ list_customers.phtml, path.phtml, report.rpt,
+ shopping_cart_setup.inc, notes/adm2.sql, notes/guest.sql: Initial
+ revision
+
+2001-04-04 13:42 matrix
+
+ * admin_constants.inc, index.html, list_cust_form.phtml,
+ list_customers.phtml, path.phtml, report.rpt,
+ shopping_cart_setup.inc, notes/adm2.sql, notes/guest.sql: imported
+ sources
+
--- /dev/null
+All application setup stuff will be in contact_setup.phtml
+1) right now if you add to the $fields array you'll still have to change
+ edit_contact.phtml and update_contact.phtml
+2) contact.sql - contains the query to build the contact table and query_db table
--- /dev/null
+\connect - postgres
+
+CREATE TABLE "contact" (
+ "id" SERIAL PRIMARY KEY,
+ "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 'f',
+ "contact_type" text
+);
+
+REVOKE ALL on "contact" from PUBLIC;
+GRANT ALL on "contact" to "nobody";
+GRANT ALL on "contact" to "postgres";
+
+REVOKE ALL on "contact_id_seq" from PUBLIC;
+GRANT ALL on "contact_id_seq" to "nobody";
+GRANT ALL on "contact_id_seq" to "postgres";
+
+CREATE TABLE "query_db" (
+ "id" SERIAL PRIMARY KEY,
+ "query_name" text,
+ "query" text,
+ "file" text,
+ "delimiter" text
+);
+
+REVOKE ALL on "query_db" from PUBLIC;
+GRANT ALL on "query_db" to "nobody";
+GRANT ALL on "query_db" to "postgres";
+
+REVOKE ALL on "query_db_id_seq" from PUBLIC;
+GRANT ALL on "query_db_id_seq" to "nobody";
+GRANT ALL on "query_db_id_seq" to "postgres";
+
+CREATE TABLE "news_response" (
+ "id" SERIAL PRIMARY KEY,
+ "subject" text,
+ "response" text,
+ "image" text,
+ "image2" text,
+ "image3" text,
+ "image_align" text,
+ "image2_align" text,
+ "image3_align" text,
+ "mailout" date default current_date,
+ "last_update" date default current_date
+);
+
+REVOKE ALL on "news_response" from PUBLIC;
+GRANT ALL on "news_response" to "postgres";
+GRANT ALL on "news_response" to "nobody";
+GRANT ALL on "news_response_id_seq" to "nobody";
+
+INSERT INTO news_response (subject,response) values ('subject','response');
+
+CREATE UNIQUE INDEX contact_id_indx ON contact(id);
+CREATE INDEX contact_email_indx ON contact(email);
+CREATE INDEX contact_fname_indx ON contact(fname);
+CREATE INDEX contact_lname_indx ON contact(lname);
+CREATE INDEX contact_create_date_indx ON contact(create_date);
+CREATE UNIQUE INDEX news_response_id_indx ON contact(id);
+CREATE UNIQUE INDEX query_db_id_indx ON contact(id);
+
+CREATE TABLE contact_inq (
+ id serial NOT NULL,
+ header text,
+ pos integer,
+ description text,
+ image text,
+ groupid integer
+);
+REVOKE ALL ON TABLE contact_inq FROM PUBLIC;
+GRANT ALL ON TABLE contact_inq TO nobody;
+REVOKE ALL ON TABLE contact_inq_id_seq FROM PUBLIC;
+GRANT ALL ON TABLE contact_inq_id_seq TO nobody;
+ALTER TABLE ONLY contact_inq
+ ADD CONSTRAINT contact_inq_pkey PRIMARY KEY (id);
+
+CREATE TABLE inq_group (
+ id SERIAL PRIMARY KEY,
+ name text
+);
+GRANT ALL ON inq_group TO nobody;
+GRANT ALL ON inq_group_id_seq TO nobody;
+
+INSERT INTO inq_group (name) VALUES ('Areas of Interest');
--- /dev/null
+<?php
+require_once '../../setup.phtml';
+require_once 'contact_setup.inc';
+
+$query = "SELECT * FROM news_response WHERE id = {$_REQUEST['id']}";
+$res = $DB->db_auto_get_data($query);
+$data['url'] = MEDIA_BASE_URL;
+$data['subject'] = $res[0]["subject"];
+$response = $res[0]["response"];
+$data['response'] = $response;
+
+$page = GLM_TOOLBOX::explode_template(NEWSLETTER_PROTOTYPE,$data);
+echo $page;
+?>
--- /dev/null
+<?php
+session_start();
+require_once '../../setup.phtml';
+require_once 'contact_setup.inc';
+/* Includes */
+extract($_REQUEST);
+function clean_array(&$array){
+ if (is_array($array)){
+ $counter = 0;
+ foreach ($array as $key=>$value){
+ if ($value == ""){
+ unset($array[$counter]);
+ }
+ $counter++;
+ }
+ }
+}
+$sess_vars = $_POST;
+$_SESSION['sess_vars'] = $sess_vars;
+$query_no = filter_var($_REQUEST['query_no'], FILTER_VALIDATE_INT);
+if (!$query_no) {
+ /* The fields array is sent as a string
+ explode it out using : as delimiter */
+ $fvalue = preg_replace("/^:/","",$fvalue);
+ $fields = explode(":",$fvalue);
+ $rfvalue = preg_replace("/^:/","",$rfvalue);
+ $return_fields = explode(":",$rfvalue);
+ $dates = preg_replace("/^:/","",$rdvalue);
+ $dates = explode(":",$dates);
+
+ clean_array($return_fields);
+ clean_array($dates);
+ if (!isset($search)) {
+ header("Location: index.phtml");
+ }
+ /* Chop off whitespaces spaces */
+ $search = chop(trim($search));
+ $search = preg_replace("/\\\|\"/", "", $search);
+ if (!$search && (count ($fields) == 1 && $fields[0] == '')) {
+ $ALL = TRUE;
+ }
+
+ function getKeywords($keywords) {
+ /* Replace the whitespace with a , */
+ $keywords = str_replace(" ",",",$keywords);
+ $keywords = str_replace(",,",",",$keywords);
+ $seperated = explode(",",$keywords);
+ /* Return exploded string */
+ return $seperated;
+ }
+
+ switch($search_type) {
+ case "1":
+ $keywords = $search;
+ $compare = "OR";
+ break;
+
+ case "2":
+ $keywords = getKeywords($search);
+ $compare = "AND";
+ break;
+
+ case "3":
+ $keywords = getKeywords($search);
+ $compare = "OR";
+ break;
+
+ case "4":
+ $keywords = getKeywords($search);
+ $compare = "AND";
+ $NOT = TRUE;
+ break;
+
+ default:
+ echo "not valid";
+ break;
+ }
+
+ if (is_array($keywords)) {
+ for ($rip=0;$rip<count($keywords);$rip++) {
+ $keywords[$rip] = trim($keywords[$rip]);
+ /* if * is at the begging the replace with .* */
+ $keywords[$rip] = preg_replace("/[\x2a]/",".*",$keywords[$rip]);
+ $keywords[$rip] = preg_replace("/[\x3f]/",".?",$keywords[$rip]);
+ $keywords[$rip] = preg_replace("/[\x2b]/",".+",$keywords[$rip]);
+ }
+ } else {
+ $keywords = trim($keywords);
+ /* if * is at the begging the replace with .* */
+ $keywords = preg_replace("/[\x2a]/",".*",$keywords);
+ $keywords = preg_replace("/[\x3f]/",".?",$keywords);
+ $keywords = preg_replace("/[\x2b]/",".+",$keywords);
+ }
+
+ switch($alter) {
+ /* $alter defines where to look in fields */
+ case "1":
+ $begin = "^";
+ $end = "";
+ break;
+
+ case "2":
+ $begin = "";
+ $end = " *$";
+ break;
+
+ default:
+ $begin = "";
+ $end = "";
+ break;
+ }
+
+ $operator = " ";
+ if ($NOT) {
+ $operator .= "!~";
+ } else {
+ $operator .= "~";
+ }
+ if ($case == "OFF") {
+ $operator .= "*";
+ }
+ if ($search == "" && ! (count ($fields) == 1 && $fields[0] == '') ) {
+ $operator = "=";
+ }
+ $operator .= " ";
+
+ /* finally, build the query string from string or array $keywords */
+ $query_string = "SELECT ".ID.",";
+ $totali = count($return_fields)-1;
+ for ($i=0;$i<count($return_fields);$i++) {
+ $query_string .= $return_fields[$i];
+ if ($i != $totali) {
+ $query_string .= ",";
+ }
+ if ($i == 8) {
+ $query_string .= "\n";
+ }
+ }
+ $totald = count($dates)-1;
+ for ($i=0;$i<count($dates);$i++) {
+ if ($dates[$i] != " " && $dates[$i] != "") {
+ if ($i == 0) {
+ $query_string .= ",";
+ }
+ }
+ $query_string .= $dates[$i];
+ if ($i != $totald) {
+ $query_string .= ",";
+ }
+ }
+ if (!$ALL) {
+ $query_string .= "\nFROM\t".TABLE." \nWHERE\t".WHERE."\nAND\t";
+ $query_string .= "(";
+ for ($b=0;$b<count($fields);$b++) {
+ $totalb = count($fields)-1;
+ if (is_array($keywords)) {
+ for ($c=0;$c<count($keywords);$c++) {
+ $totalc = count($keywords)-1;
+ $query_string .= $fields[$b].$operator."'".
+ $begin.$keywords[$c].$end."'";
+ if ($c != $totalc) {
+ $query_string .= " \n$compare\t";
+ }
+ }
+ } else {
+ $query_string .= $fields[$b].$operator."'".
+ $begin.$keywords.$end."'";
+ }
+ if ($b != $totalb) {
+ $query_string .= " \n$compare\t";
+ }
+ }
+ $query_string .= ")";
+ } else {
+ $query_string .= "\nFROM\t".TABLE." \nWHERE\t".WHERE."\n";
+ }
+ if (is_array ($boolean) ) {
+ foreach ($boolean as $bool_key => $bool_val) {
+ if ($_POST[$bool_key] == "1") {
+ $bstring[] = " $bool_key = 't'";
+ } elseif ($_POST[$bool_key] == "0") {
+ $bstring[] = " $bool_key = 'f'";
+ }
+ }
+ if (is_array($bstring)) {
+ $query_string .= ' and ('.implode(" $compare ",$bstring) .') ';
+ }
+ }
+ if( is_array( $dropdowns ) ) {
+ foreach( $dropdowns as $drop_key => $drop_val ) {
+ if( is_array( $_POST[$drop_key] ) ) {
+ foreach( $_POST[$drop_key] as $mdrop_key => $mdrop_val ){
+ if( $mdrop_val != '' ){
+ $dstring[] = " $drop_key $operator ':".$mdrop_val.":'";
+ }
+ }
+ }elseif( !is_array( $_POST[$drop_key] ) ) {
+ if( $_POST[$drop_key] != '' ){
+ $dstring[] = " $drop_key = '".$_POST[$drop_key]."'";
+ }
+ }
+ }
+ if( is_array($dstring) ) {
+ $query_string .= ' and ('.implode(" $compare ",$dstring).' ) ';
+ }
+ }
+ if (is_array ($cols) ) {
+ foreach ($cols as $ikey => $ival) {
+ $cstring[] = " interest $operator ':$ival:'";
+ }
+ if (is_array($cstring)) {
+ $query_string .= ' and ('.implode(" $compare ",$cstring).') ';
+ }
+ }
+ if (isset($fp_month)) {
+ $fp_str = mktime(0,0,0,$fp_month,$fp_day,$fp_year);
+ $tp_str = mktime(0,0,0,$tp_month,$tp_day,$tp_year);
+ $fa_str = mktime(0,0,0,$fa_month,$fa_day,$fa_year);
+ $ta_str = mktime(0,0,0,$ta_month,$ta_day,$ta_year);
+
+ if ($fp_str<$tp_str) {
+ $fp_date = $fp_month."/".$fp_day."/".$fp_year;
+ $tp_date = $tp_month."/".$tp_day."/".$tp_year;
+ $query_string .= " AND purch_date >= '$fp_date'
+ AND purch_date <= '$tp_date'";
+ }
+ if ($fa_str<$ta_str) {
+ $fa_date = $fa_month."/".$fa_day."/".$fa_year;
+ $ta_date = $ta_month."/".$ta_day."/".$ta_year;
+ $query_string .= " AND access_date >= '$fa_date'
+ AND access_date <= '$ta_date'";
+ }
+ if ($fp_str>$tp_str) {
+ $fp_date = $fp_month."/".$fp_day."/".$fp_year;
+ $tp_date = $tp_month."/".$tp_day."/".$tp_year;
+ $query_string .= " AND purch_date <= '$tp_date'";
+ }
+ if ($fa_str>$ta_str) {
+ $fa_date = $fa_month."/".$fa_day."/".$fa_year;
+ $ta_date = $ta_month."/".$ta_day."/".$ta_year;
+ $query_string .= " AND access_date <= '$ta_date'";
+ }
+ }
+ if (isset($fc_month)) {
+ $fc_str = mktime(0,0,0,$fc_month,$fc_day,$fc_year);
+ $tc_str = mktime(0,0,0,$tc_month,$tc_day,$tc_year);
+
+ if ($fc_str<$tc_str) {
+ $fc_date = $fc_month."/".$fc_day."/".$fc_year;
+ $tc_date = $tc_month."/".$tc_day."/".$tc_year;
+ $query_string .= " AND create_date >= '$fc_date'
+ AND create_date <= '$tc_date'";
+ }
+ if ($fc_str>$tc_str) {
+ $fc_date = $fc_month."/".$fc_day."/".$fc_year;
+ $tc_date = $tc_month."/".$tc_day."/".$tc_year;
+ $query_string .= " AND create_date <= '$tc_date'";
+ }
+ }
+} else {
+ $sql = "
+ SELECT query_name,query,delimiter,file
+ FROM query_db
+ WHERE id = $query_no";
+ $stmt = $DB->dbh->query($sql);
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+ $query_name = $row['query_name'];
+ $file = $row['file'];
+ $delimiter = $row['delimiter'];
+ $query_string = $row['query'];
+ //var_dump($query_string);
+ //exit;
+}
+/* Thought the customer would like to see what's in the query */
+$showq = str_replace("SELECT","Return\n",$query_string);
+$showq = str_replace ("\nFROM\t".TABLE." \nWHERE\t".WHERE."\nAND\t",
+" \nfrom the contact database \nwhere ",$showq);
+$showq = str_replace ("\nFROM\t".TABLE." \nWHERE\t".WHERE."\n",
+" \nfrom the contact database",$showq);
+$showq = str_replace("fname","first name",$showq);
+$showq = str_replace("cust_id,","",$showq);
+$showq = str_replace("lname","last name",$showq);
+$showq = str_replace("!~*","does not contain",$showq);
+$showq = str_replace("!~","does not contain",$showq);
+$showq = str_replace("~*","contains",$showq);
+$showq = str_replace("~","is in",$showq);
+$showq = str_replace("does not contain '^"," does not start with ",$showq);
+$showq = str_replace("contains '^"," starts with ",$showq);
+$showq = str_replace("is in '^"," starts with ",$showq);
+$showq = str_replace("$"," in the ending ",$showq);
+$showq = str_replace("OR","or",$showq);
+$showq = str_replace("AND","and",$showq);
+$showq = str_replace("'","",$showq);
+if (!$ALL) {
+ if ($case == "OFF") {
+ $showq .= "\n(case insensitive match)";
+ } else {
+ $showq .= "\n(case sensitive match)";
+ }
+}
+if (isset($file) && $file != "") {
+ $showq .= "\noutput 1 file in ";
+ if ($file == "rpt") {
+ $showq .= "text";
+ }elseif ($file == "gz") {
+ $showq .= "tar ball";
+ }else {
+ $showq .= "zip";
+ }
+ if ($delimiter == "csv") {
+ $showq .= " format using ".$delimiter;
+ } else {
+ $showq .= " format using ".$delimiter." as delimiter";
+ }
+}
+$showq .= ".";
+$query = $query_string;
+
+GLM_TOOLBOX::top("QUERY BUILDER PAGE","");
+GLM_TOOLBOX::html_nav_table($nav,$navWidth);
+?>
+<script src="<?php echo MEDIA_BASE_URL."admin/wm.js"?>"></script>
+<script src="<?php echo MEDIA_BASE_URL."admin/msg.js"?>"></script>
+
+<table id="admin-list-table">
+<tr>
+ <th bgcolor="#2f4f4f" class="theader">
+ Submit Query
+ </th>
+ </tr>
+ <tr>
+ <td><a href="index.phtml">Go Back to Query page</a></td>
+ </tr>
+ <tr>
+ <td>
+ <?php echo nl2br($showq)?>
+ <br>
+ <?php if (isset($query_name)) {
+ echo "Query ".$query_name." Recalled";
+ }?>
+
+ <form action="list_contact.phtml" method="POST">
+ <input type="hidden" name="delimiter" value="<?php echo $delimiter?>">
+ <input type="hidden" name="file" value="<?php echo $file?>">
+ <?php
+ if (!$_GET['query_no']) {
+ ?>
+ <input type="hidden" name="query_string" value="<?php echo $query_string?>">
+ <?php
+ } else {
+ ?>
+ <input type="hidden" name="query_no" value="<?php echo $query_no;?>">
+ <?php
+ }
+ ?>
+ <input type="hidden" name="Submit" value="Submit Query">
+ <center>
+ <input type="submit" value="Send Query">
+ </form>
+ </center>
+ </td>
+ </tr>
+</table>
+<script lang="javascript">
+ var o_save = new Object();
+ o_save.url = 'query_save.phtml';
+ o_save.name = 'savewin';
+ o_save.width = 510;
+ o_save.height = 150;
+</script>
+<table>
+ <tr>
+ <th bgcolor="#2f4f4f" class="theader">
+ Do you wish to save this query for future use?
+ </th>
+ </tr>
+ <tr>
+ <td>
+ <a href="#" onClick="
+ glm_open(o_save);
+ return(false);
+ ">Save This Report</a>
+ </td>
+</tr>
+</table>
+
+<?php
+/* Save the query with (current) as query_name */
+$qs = "SELECT id
+ FROM query_db
+ WHERE query_name = '(current)'";
+$res = $DB->dbh->query($qs);
+if (!$rowId = $res->fetchColumn()) {
+ $sql = "
+ INSERT INTO query_db
+ (query_name, query, file, delimiter)
+ VALUES
+ ('(current)', :query, :file, :delimiter)";
+} else {
+ $sql = "
+ UPDATE query_db
+ SET query = :query,
+ file = :file,
+ delimiter = :delimiter
+ WHERE id = :id";
+}
+// save query
+$stmt = $DB->dbh->prepare($sql);
+$stmt->bindParam(':query', $query);
+$stmt->bindParam(':file', $file);
+$stmt->bindParam(':delimiter', $delimiter);
+if ($rowId) {
+ $stmt->bindParam(':id', $rowId);
+}
+$stmt->execute();
+
+GLM_TOOLBOX::footer();
+?>
--- /dev/null
+<?php
+require_once '../../setup.phtml';
+require_once 'contact_setup.inc';
+
+if(!isset($file)) $file = "";
+if(!isset($delimiter)) $delimiter = "";
+
+$qs = "INSERT
+ INTO query_db (query_name,query,file,delimiter)
+ (select '$query_name',query,file,delimiter from query_db where query_name = '(current)' limit 1 offset 0)";
+if(!$DB->db_auto_exec($qs))
+ {
+ html_error(DB_ERROR_MSG.$qs,1);
+ }
+GLM_TOOLBOX::html_header("Saving Query","Saved","");
+?>
+Query is saved as <?php echo $query_name?>
+<center><a href="#" onClick="window.close();return(false);">Close This
+Window</a></center>
--- /dev/null
+<html>
+<body bgcolor=white>
+<table bgcolor="#e0e0e0" width=500 cellpadding=4 cellspacing=0 border=0>
+ <tr>
+ <td>Name of Report
+
+ <form name="form2" action="query_db.phtml" method="POST">
+ <input type="hidden" name="query" value="<?php echo $query_string?>">
+ <input type="hidden" name="delimiter" value="<?php echo $delimiter?>">
+ <input type="hidden" name="file" value="<?php echo $file?>">
+ <input name="query_name">
+ <input type="submit" name="Submit" value="Save">
+ </form>
+ </td>
+</tr>
+</table>
+</body>
+</html>
--- /dev/null
+<?php
+require_once '../../setup.phtml';
+require_once 'contact_setup.inc';
+
+
+switch ($Command) {
+
+case "Update":// {{{
+ $location = "emails.php";
+ $dbh = Toolkit_Database::getInstance();
+ $id = filter_input(INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT);
+ if (!$id) {
+ break;
+ }
+
+ $sql = "
+ UPDATE news_response
+ SET subject = :subject,
+ response = :response,
+ last_update = current_date
+ WHERE id = :id";
+ $update = $dbh->prepare($sql);
+ $update->bindParam(
+ ':subject',
+ stripslashes($subject),
+ PDO::PARAM_STR
+ );
+ $update->bindParam(
+ ':response',
+ stripslashes($response),
+ PDO::PARAM_STR
+ );
+ $update->bindParam(
+ ':id',
+ $id,
+ PDO::PARAM_INT
+ );
+ $update->execute();
+ break;// }}}
+
+case "Insert":// {{{
+ $dbh = Toolkit_Database::getInstance();
+ $sql = "
+ INSERT INTO news_response
+ (last_update,subject,response)
+ VALUES
+ (current_date,:subject,:response)";
+ $insert = $dbh->prepare($sql);
+ $insert->bindParam(
+ ':subject',
+ stripslashes($subject),
+ PDO::PARAM_STR
+ );
+ $insert->bindParam(
+ ':response',
+ stripslashes($response),
+ PDO::PARAM_STR
+ );
+ $insert->execute();
+ $location = "emails.php";
+
+ break;// }}}
+
+case "Cancel":// {{{
+ $location = "emails.php";
+ break;// }}}
+
+case "Delete":// {{{
+ $query = "
+ DELETE FROM news_response
+ WHERE id = $id;";
+ $DB->db_exec( $query );
+ $location = "emails.php";
+ break;// }}}
+
+default:// {{{
+ GLM_TOOLBOX::html_error("incorrect value for Command",1);
+ break;// }}}
+}
+
+header("Location: $location");
+?>
--- /dev/null
+<?php
+require_once '../../setup.phtml';
+require_once 'contact_setup.inc';
+$location = "list_contact.phtml?back=1&start=" . $start;
+
+if (is_array($contact_type)) {
+ $contact_type = ":".implode(":",$contact_type).":";
+}
+if (is_array($interest)) {
+ $interest = ":".implode(":",$interest).":";
+}
+GLM_TOOLBOX::http_strip($url);
+
+$LAST = count($DB_fields)-1;
+if ($REQUEST_METHOD == "POST" || $Command == "Delete") {
+ switch ($Command) {
+ case "Delete":
+ $qs = "DELETE FROM ".TABLE."
+ WHERE ".ID." = $id";
+
+ if (!$DB->db_auto_exec($qs)) {
+ $ERRORS .= pg_errormessage($dbd).$qs;
+ }
+ $location .= '&Action=Contact+Deleted';
+
+ break;
+
+ case "Cancel":
+ break;
+
+ default:
+ $ERRORS .= "incorrect value for Command";
+ break;
+
+ }
+
+ header("Location: $location");
+}
+?>
--- /dev/null
+<?php
+include "../../setup.phtml";
+include "contact_setup.inc";
+switch ($Command) {
+case "Move":
+ $qs = "select pos,id from contact_inq where id = $id";
+ if (!$result = $DB->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 contact_inq where pos < $pos and pos >= $newpos and groupid = $groupid order by pos";
+ if(!$res = $DB->db_exec($qs)) {
+ GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs, 0);
+ }
+ $counter = ($newpos + 1);
+ $totalNum = $DB->db_numrows($res);
+ for ($i = 0;$i < $totalNum; $i++) {
+ $res_data = $DB->db_fetch_array($res, $i, PGSQL_ASSOC);
+ $res_id = $res_data['id'];
+ $res_pos = $res_data['pos'];
+ $qs = "update contact_inq 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 contact_inq where pos > $pos and pos <= $newpos and groupid = $groupid order by pos";
+ if (!$res = $DB->db_exec($qs)) {
+ GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs, 0);
+ }
+ $counter = ($pos);
+ $totalNum = $DB->db_numrows($res);
+ for ( $i = 0; $i < $totalNum; $i++) {
+ $res_data = $DB->db_fetch_array($res, $i, PGSQL_ASSOC);
+ $res_id = $res_data['id'];
+ $res_pos = $res_data['pos'];
+ $qs = "update contact_inq set pos = $counter where id = $res_id";
+ if (!$DB->db_exec($qs)) {
+ GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs, 0);
+ }
+ $counter++;
+ }
+ }
+ $qs = "update contact_inq set pos = $newpos where id = $id";
+ if (!$DB->db_exec($qs)) {
+ GLM_TOOLBOX::html_error(DB_ERROR_MSG.$qs, 0);
+ }
+ break;
+
+case "Edit":
+ if ($_POST['new_group']) {
+ $query = "select id from inq_group where name = '".$_POST['new_group']."'";
+ if ($newData = $DB->db_auto_get_data($query)) {
+ // already exists use the id returned
+ $groupid = $newData[0]['id'];
+ } else {
+ $query = "
+ INSERT INTO inq_group
+ (name)
+ VALUES
+ ('{$_POST['new_group']}')
+ RETURNING id";
+ if ($newData = $DB->db_auto_get_data($query)) {
+ $groupid = $newData[0]['id'];
+ }
+ }
+ }
+ $qs = "update contact_inq set header = '$header',image = '$image_name',description = '$description',groupid = $groupid where id = $id;";
+ $DB->db_exec($qs);
+ break;
+
+case "Add":
+ if ($_POST['new_group']) {
+ $query = "select id from inq_group where name = '".$_POST['new_group']."'";
+ if ($newData = $DB->db_auto_get_data($query)) {
+ // already exists use the id returned
+ $groupid = $newData[0]['id'];
+ } else {
+ $query = "
+ INSERT INTO inq_group
+ (name)
+ VALUES
+ ('{$_POST['new_group']}')
+ RETURNING id";
+ if ($newData = $DB->db_auto_get_data($query)) {
+ $groupid = $newData[0]['id'];
+ }
+ }
+ }
+ $qs = "select MAX(pos) as maxpos from contact_inq where groupid = $groupid";
+ $res = $DB->db_exec($qs);
+ $row = $DB->db_fetch_array($res,0,PGSQL_ASSOC);
+ $nextpos = $row[maxpos];
+ $nextpos++;
+ $qs = "insert into contact_inq (header,description,image,pos,groupid) values ('$header','$description','$image_name',$nextpos,$groupid);";
+ $DB->db_exec($qs);
+ break;
+
+case "Delete":
+ $qs = "delete from contact_inq where id = $id";
+ $DB->db_exec($qs);
+ if ($_REQUEST['old_groupid']) {
+ $qs = "select pos,id from contact_inq where pos > $oldpos and groupid = $old_groupid order by pos";
+ $res = $DB->db_exec($qs);
+ $oldcatid_counter = $oldpos;
+ $totalNum = $DB->db_numrows($res);
+ for ($i = 0; $i < $totalNum; $i++) {
+ $row = $DB->db_fetch_array($res, $i, PGSQL_ASSOC);
+ $qs = "update contact_inq set pos = $oldcatid_counter where id = $row[id]";
+ }
+ $DB->db_exec($qs);
+ }
+ break;
+}
+header("Location: contact_inquiry.phtml");
--- /dev/null
+function isblank(s) {
+ for(var i = 0; i < s.length; i++) {
+ var c = s.charAt(i);
+ if((c != ' ') && (c != '\n') && (c != '\t'))
+ return(false);
+ }
+ return(true);
+}
+
+function verify(f) {
+ var msg;
+ var empty_fields = "";
+ var errors = "";
+
+ for(var i = 0; i < f.length; i++) {
+ var e = f.elements[i];
+ if(((e.type == "text") || (e.type == "textarea")) && !e.optional) {
+ if((e.value == null) || (e.value == "") || isblank(e.value)) {
+ empty_fields += "\n " + e.r;
+ continue;
+ }
+
+ if(e.d) {
+ if(isNaN(Date.parse(e.value)))
+ errors += "- The field " +e.r+" must be formated like 01/17/2001\n";
+ }
+ if(e.numeric || (e.min != null) || (e.max != null)) {
+ if(e.i) {
+ var v = parseInt(e.value);
+ if(v != e.value) {
+ errors += "- The field " +e.r + " must be a ";
+ errors += "number with no decimal\n";
+ continue;
+ }
+ }
+ else
+ var v = parseFloat(e.value);
+ if(isNaN(v) ||
+ ((e.min != null) && (v < e.min)) ||
+ ((e.max != null) && (v > e.max))) {
+
+ errors += "- The field " + e.r + " must be a number";
+ if(e.min != null)
+ errors += " that is greater than " + e.min;
+ if(e.max != null && e.min != null)
+ errors += " and less than " + e.max;
+ else if (e.max != null)
+ errors += " that is less than " + e.max;
+ errors += ".\n";
+ }
+ }
+ }
+ }
+
+ if(!empty_fields && !errors)
+ return(true);
+
+ msg = "_____________________________________________________\n\n";
+ msg +="The form was not submitted because of the following error(s).\n";
+ msg +="Please correct these error(s) and re-submit.\n";
+ msg +="_____________________________________________________\n\n";
+
+ if(empty_fields) {
+ msg += "- The following required field(s) are empty:"
+ + empty_fields + "\n";
+ if(errors)
+ msg += "\n";
+ }
+ msg += errors;
+ alert(msg);
+ return(false);
+}
--- /dev/null
+<?php
+require_once '../../setup.phtml';
+require_once 'contact_setup.inc';
+define("STYLE","main.css");
+if ($_REQUEST['id'] == '') {
+ $_REQUEST['id'] = 1;
+}
+
+GLM_TOOLBOX::top("AutoReponse for Newsletter", HELP_BASE."response.phtml?key=edit+section");
+GLM_TOOLBOX::html_nav_table($nav,$navWidth);
+
+echo'<iframe src="preview.phtml?id='.$_REQUEST['id'].'"
+width="780" height="480"
+align="center">
+</iframe>
+
+ </td>
+</tr>
+</table>';
+
+GLM_TOOLBOX::footer();
+?>
--- /dev/null
+function glm_open(o) {
+ var x = (screen.width/2) - (o.width/2);
+ var y = (screen.height/2) - (o.height/2);
+ var args = "width="+o.width+",height="+o.height+",screenX="+x+",screenY="+y+",top="+y+",left="+x;
+ if(o.scroll == true)
+ args += ",scrollbars=1";
+ //args += "\'";
+ //alert(args);
+ pow=window.open(o.url,o.name,args);
+ //confirm(args);
+ if (pow.opener == null)
+ pow.opener = self;
+}
--- /dev/null
+<?php
+/**
+ * blocks.php
+ *
+ * PHP version 5.2
+ *
+ * @category Admin
+ * @package Blocks
+ * @author Steve Sutton <steve@gaslightmedia.com>
+ * @copyright 2012 Gaslight Media
+ * @license Gaslight Media
+ * @version SVN: (0.1)
+ * @link <>
+ */
+/**
+ * required files
+ */
+require_once '../setup.phtml';
+// get Application config file loaded into Zend_Config
+$config = new Zend_Config_Ini(
+ BASE . 'Toolkit/Blocks/application.ini',
+ strtolower($_ENV['GLM_HOST_ID'])
+);
+// add our custom jquery ui js file to all areas of this admin side application
+$jQueryVersion = $config->jqueryui->version;
+$jQueryTheme = $config->jqueryui->theme;
+$GLOBALS['bottomScripts'][] = JQUERY_UI_CDN_JS;
+$GLOBALS['styleSheets'][] = JQUERY_UI_CDN_CSS;
+// create Registry
+$registry = new Toolkit_Registry;
+$registry->dbh = Toolkit_Database::getInstance();
+$registry->logger = Toolkit_Logger::getLogger();
+$registry->router = new Toolkit_Router($registry);
+$registry->router->setPath($config->router->path);
+$registry->router->setApplication($config->router->application);
+$registry->appConfig = $config;
+
+// call loader()
+$html = $registry->router->loader();
+
+
+GLM_TOOLBOX::top($config->application->name, '');
+echo $html;
+GLM_TOOLBOX::footer();
--- /dev/null
+<?php
+require_once '../setup.phtml';
+
+// application configuration
+$conf = new Config;
+$confRoot=& $conf->parseConfig(
+ BASE . 'Toolkit/Coupons/config.ini',
+ 'IniFile'
+);
+
+// get reference to [conf] section of config file
+$appName
+ = $confRoot->getItem('section', 'conf')
+ ->getItem('directive', 'applicationName')
+ ->getContent();
+
+$navigation = new Toolkit_Coupons_Navigation(
+ new HTML_Menu(),
+ new HTML_Menu_DirectRenderer()
+);
+
+$navArray = $navigation->getNavStructure($confRoot);
+$navHtml = $navigation->renderPageNav($navArray, 'rows');
+$c = new Toolkit_Coupons_Controller();
+$coupons = $c->toHtml(
+ Toolkit_Database::getInstance(),
+ $confRoot
+);
+
+GLM_TOOLBOX::top($appName, '');
+echo $navHtml;
+echo $coupons;
+GLM_TOOLBOX::footer();
+?>
--- /dev/null
+<?php
+require_once '../setup.phtml';
+// Registry Object to hold global objects and setting for application
+$registry = new Toolkit_Registry;
+// create a Zend Config Object and store into Registry
+$config = new Zend_Config_Ini(
+ BASE . 'Toolkit/Photos/application.ini',
+ strtolower($_ENV['GLM_HOST_ID'])
+);
+$registry->config = $config;
+$registry->page = MEDIA_BASE_URL . 'admin/photos.php';
+$appConfig = $config->application->toArray();
+$registry->dbh = Toolkit_Database::getInstance();
+$registry->logger = Toolkit_Logger::getLogger();
+$registry->router = new Toolkit_Router($registry);
+$registry->router->setPath($appConfig['path']);
+$registry->router->setApplication($appConfig['application']);
+
+$html = $registry->router->loader();
+
+echo $html;
\ No newline at end of file
--- /dev/null
+<?php
+require_once '../setup.phtml';
+
+// application configuration
+$conf = new Config;
+$confRoot=& $conf->parseConfig(
+ BASE . 'Toolkit/Videos/config.ini',
+ 'IniFile'
+);
+
+// get reference to [conf] section of config file
+$appName
+ = $confRoot->getItem('section', 'conf')
+ ->getItem('directive', 'applicationName')
+ ->getContent();
+
+$navigation = new Toolkit_Videos_Navigation(
+ new HTML_Menu(),
+ new HTML_Menu_DirectRenderer()
+);
+
+$navArray = $navigation->getNavStructure($confRoot);
+$navHtml = $navigation->renderPageNav($navArray, 'rows');
+$c = new Toolkit_Videos_Controller();
+$videos = $c->toHtml(
+ Toolkit_Database::getInstance(),
+ $confRoot
+);
+
+GLM_TOOLBOX::top($appName, '');
+echo $navHtml;
+echo $videos;
+GLM_TOOLBOX::footer();
\ No newline at end of file
retailShop.application = Off
; Turn the contact application On or Off
-contactdb.application = Off
+contactdb.application = On
; Set the first year available in the year select lists
; these are in the report builder form for admin
; site > admin > contacts > report builder
constantcontact.list.0 = Off
; Turn the coupon application On or Off
-coupons.application = Off
+coupons.application = On
; Turn the event application On or Off
eventdb.application = Off
news.page = Off
; Turn the photo gallery application On or Off
-photo_gallery.application = Off
+photo_gallery.application = On
; Turn the rotating image application On or Off
rotating_images.application = Off
ticketing.cat_seo = Off
employment.application = Off
-videos.application = Off
+videos.application = On
seasons.application = Off
-blocks.application = Off
+blocks.application = On
; development server configuration data inherits from production and
; overrides values as necessary
[development : production]
--- /dev/null
+$(document).ready(function(){
+ $("#description").textlimit("#charleft", 600);
+});