PHP – Chris Gilligan » new media https://chrisgilligan.com portfolio of web work Wed, 10 Jul 2019 22:12:16 +0000 en-US hourly 1 https://wordpress.org/?v=5.4.1 Integrating Content from External Sources into OU Campus Using RSS, PHP, and JavaScript https://chrisgilligan.com/consulting/integrating-content-from-external-sources-into-ou-campus-using-rss-php-and-javascript/ https://chrisgilligan.com/consulting/integrating-content-from-external-sources-into-ou-campus-using-rss-php-and-javascript/#respond Tue, 23 Feb 2016 00:50:35 +0000 https://chrisgilligan.com/?p=2386 The web team of the University of Tennessee at Chattanooga uses PHP and RSS to syndicate blog content, news releases, and calendar events into their main website. PHP SimpleXML is used to parse the XML of the RSS feeds. We import a variety of feeds, from WordPress, from Master Calendar, and from other sites such as […]

The post Integrating Content from External Sources into OU Campus Using RSS, PHP, and JavaScript appeared first on Chris Gilligan » new media.

]]>

The web team of the University of Tennessee at Chattanooga uses PHP and RSS to syndicate blog content, news releases, and calendar events into their main website.

PHP SimpleXML is used to parse the XML of the RSS feeds. We import a variety of feeds, from WordPress, from Master Calendar, and from other sites such as an external athletics CMS. WordPress provides some RSS features, including RSS from categories, tags and search strings, but we have added media attachments and a customized template to output a more complicated RSS feed on the University home page.

News releases, events and content from WordPress via RSS

Example web pages:

WordPress plugin & PHP to add media attachments to RSS feed

Example RSS feeds (view XML/XSL styled page in FireFox; View Source to see XML structure, namespaces, node names and structure):

Custom WordPress RSS feed template, followed by the functions call to load and create it:

<?php
/*
Template Name: Custom Current Headlines Feed

*/

$numposts = 10;
$category_id = get_cat_ID('Current Headlines');

function custom_rss_date( $timestamp = null ) {
  $timestamp = ($timestamp==null) ? time() : $timestamp;
  echo date(DATE_RSS, $timestamp);
}

function custom_rss_text_limit($string, $length, $replacer = '&hellip;') { 
  $string = strip_tags($string);
  if(strlen($string) > $length) 
    return (preg_match('/^(.*)\W.*$/', substr($string, 0, $length+1), $matches) ? $matches[1] : substr($string, 0, $length)) . $replacer;   
  return $string; 
}

$posts = query_posts('cat='.$category_id.'&showposts='.$numposts);

$lastpost = $numposts - 1;



header('Content-Type: ' . feed_content_type('rss-http') . '; charset=' . get_option('blog_charset'), true);
$more = 1;

echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>'; ?>

<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	<?php do_action('rss2_ns'); ?>
>

<channel>
	<title><?php bloginfo_rss('name'); wp_title_rss(); ?></title>
	<atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
	<link><?php bloginfo_rss('url') ?></link>
	<description><?php bloginfo_rss("description") ?></description>
	<lastBuildDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_lastpostmodified('GMT'), false); ?></lastBuildDate>
	<language><?php bloginfo_rss( 'language' ); ?></language>
	<sy:updatePeriod><?php echo apply_filters( 'rss_update_period', 'hourly' ); ?></sy:updatePeriod>
	<sy:updateFrequency><?php echo apply_filters( 'rss_update_frequency', '1' ); ?></sy:updateFrequency>
	<?php do_action('rss2_head'); ?>
	<?php while( have_posts()) : the_post(); ?>
	<item>
		<title><?php the_title_rss() ?></title>
		<link><?php the_permalink_rss() ?></link>
		<comments><?php comments_link_feed(); ?></comments>
		<pubDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_post_time('Y-m-d H:i:s', true), false); ?></pubDate>
		<dc:creator><?php the_author() ?></dc:creator>
<?php the_category_rss('rss2') ?>
		<guid isPermaLink="false"><?php the_guid(); ?></guid>
<?php if (get_option('rss_use_excerpt')) : ?>
		<description><![CDATA[<?php get_the_excerpt(); ?>]]></description>
<?php else : ?>
		<description><?php echo '<![CDATA['.custom_rss_text_limit($post->post_content, 256).']]>';  ?></description>
<?php $content = get_the_content_feed('rss2'); ?>
	<?php if ( strlen( $content ) > 0 ) : ?>
		<content:encoded><![CDATA[<?php echo $content; ?>]]></content:encoded>
	<?php else : ?>
		<content:encoded><![CDATA[<?php the_excerpt(); ?>]]></content:encoded>
	<?php endif; ?>
<?php endif; ?>
		<wfw:commentRss><?php echo esc_url( get_post_comments_feed_link(null, 'rss2') ); ?></wfw:commentRss>
		<slash:comments><?php echo get_comments_number(); ?></slash:comments>
<?php rss_enclosure(); ?>
<?php do_action('rss2_item'); ?>
		</item>
	<?php endwhile; ?>
</channel>
</rss>
/* Custom RSS Feed for Home Page headlines */

function create_my_customfeed() {
load_template( get_stylesheet_directory() . '/headlines-customfeed.php');
}
add_action('do_feed_headlines', 'create_my_customfeed', 10, 1);

OU Campus PHP helper file and code asset

To parse an existing external RSS feed, such as a standard or custom WordPress feed, we use a helper file that employs PHP’s simplexml_load_string to load the targeted RSS feed, traverse the XML document, select node content, then echo out a block of styled html for each set of targeted XML nodes. The helper file accepts the $feed variable to specify the location of the targeted feed, and the $maxitems variable to specify the number of items to select from the top of the that feed.

On its own, the PHP helper file can be hit in a browser, to verify the targeted feed type exists and is parsed correctly. The browser will return an un-styled html page from the helper file URL.

The OU Campus Code Asset includes the helper file, over-rides the helper’s default variables, is and is very simple to copy and modify, according to the intended target feed and desired number of items to be presented on the final page. Many different Assets can include a single helper file.

(Vinit from OmniUpdate outlined a much better way to handle the feed URL and number of items in his Server Side Scripting class: via PCF Page Parameters.)

PHP file

  • parses feed and displays HTML
    • variables set to defaults for testing
      • may need to verify feed access and XML structure
  • various types of display html
    • title, excerpt, thumbnail from WordPress
    • title only from WordPress
    • RSS feed with formatting or namespaces different from WordPress
<?php

$input = $_SERVER['QUERY_STRING'];
parse_str($input);

if (!isset($feed))//script or page property will choose which feed to display
	$feed = "http://blog.utc.edu/news/headlines.xml/";

if(!isset($maxitems))
	$maxitems = 3;

$file = file_get_contents($feed);
$file = str_ireplace('src="http://', 'src="//', $file);
$file = str_ireplace('media:content url="http://', 'media:content url="//', $file);
$file = str_ireplace('media:thumbnail url="http://', 'media:thumbnail url="//', $file);

$sxml = simplexml_load_string($file);

$i = 0;
	foreach ($sxml->channel->item as $item) {
		if (++$i > $maxitems) {
				break;
			}
		$namespaces      = $item->getNameSpaces( true );
		$content         = isset($namespaces['content']) ? $item->children( $namespaces['content'] ) : '';
		$content_encoded = isset($content->encoded)      ? $content->encoded                         : '';
		$media           = isset($namespaces['media'])   ? $item->children( $namespaces['media'] )   : '';
		$html       = "<div class=\"row-fluid\">"
					.     "<h3><a href=\"{$item->link}\">{$item->title}</a></h3>"
					.     "{$content_encoded}"
					.  "</div>";
	echo($html);
}
?>
<script>
	$(document).ready(function(){
		$('.sidebar img').removeClass().addClass('thumbnail pull-right span5');
		$('aside.well img').removeClass().addClass('thumbnail pull-right span5');
	});
</script>

OU Campus Assets

  • simple structure
    • specify RSS source
    • number of posts to display
<?php
$feed = "//blog.utc.edu/hr/category/benefits/feed/";
include($_SERVER['DOCUMENT_ROOT']. '/_resources/php/get-headlines-sidebar.php');
$maxitems = 5;
?>

(Vinit from OmniUpdate outlined a much better way to handle the feed URL and number of items in his Server Side Scripting class: via PCF Page Parameters.)

More Speed

After you verify the final production page, you should set up cron jobs for any external feeds that are created via database calls on the external servers. A WordPress feed will require a bit of PHP and MySQL work to generate the RSS feed. This requires some processing, and will introduce a delay in service of the OU Campus PHP page. To avoid this latency, we create cron jobs on the production server to periodically fetch the feeds and cache them locally on the production server. The speed increase for the final page product is noticeable.

If your OU Campus Sites include development, test, training, or mobile Sites, you will want to duplicate the local static feeds on all of the OU Sites.

If you control an external WordPress site, you can employ caching mechanisms or plugins to more efficiently serve RSS feeds.

  • cache RSS feeds via WordPress plugin, e.g. W3  Total Cache
  • cron job to fetch feeds to local production servers
  • minimize external requests for faster page load

This cron job can be placed in /etc/cron.hourly to fetch WordPress feeds, check lastBuildDate, and compare that to the existing build date, and create a cached RSS xml file.

#!/bin/bash

# Preload WordPress Feeds for Website

# UTC News
wget http://blog.utc.edu/news/headlines.xml/ -O /data/web/prod/www/_resources/rss/wp-news.tmp >/dev/null 2>&1
TMP_LASTBUILD="$(xml_grep '/rss/channel/lastBuildDate' --text_only /data/web/prod/www/_resources/rss/wp-news.tmp)"
XML_LASTBUILD="$(xml_grep '/rss/channel/lastBuildDate' --text_only /data/web/prod/www/_resources/rss/wp-news.xml)"
MIMETYPE=`file -b --mime-type /data/web/prod/www/_resources/rss/wp-news.tmp`
if [ "$MIMETYPE" == "application/xml" -a  "$TMP_LASTBUILD" != "$XML_LASTBUILD" ] ; then
    mv /data/web/prod/www/_resources/rss/wp-news.tmp /data/web/prod/www/_resources/rss/wp-news.xml
fi

# Duplicate for development, test & training environments
cp -p /data/web/prod/www/_resources/rss/wp*.xml /data/web/test/www/_resources/rss/
cp -p /data/web/prod/www/_resources/rss/wp*.xml /data/web/test/train/_resources/rss/
cp -p /data/web/prod/www/_resources/rss/wp*.xml /data/web/dev/www/_resources/rss/

For other RSS sources, the structure may be different; maybe we can’t do a lastBuildDate check. And… some servers may not respond to a default wget request from a shell script. No problem: just specify --header and --user-agent, don’t do the lastBuildDate check, and just write the RSS XML file.

#!/bin/bash

# Preload GoMocs Feeds for Website


# Gomocs.com News
wget  --header="Accept: text/html" --user-agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:21.0) Gecko/20100101 Firefox/21.0" http://www.gomocs.com/rss.aspx -O /data/web/prod/www/_resources/gomocs-news.xml

# Duplicate for development, test & training environments
cp -p /data/web/prod/www/_resources/rss/gomocs*.xml /data/web/test/www/_resources/rss/
cp -p /data/web/prod/www/_resources/rss/gomocs*.xml /data/web/test/train/_resources/rss/
cp -p /data/web/prod/www/_resources/rss/gomocs*.xml /data/web/dev/www/_resources/rss/

Event Calendar RSS feeds from Master Calendar via RSS

Example pages that include feeds from Master Calendar. MC has a very rudimentary RSS output of title, date/time and description. MC caches its RSS feeds by default, and expects a lot of traffic to the feed locations, so it is not so necessary to create cron jobs to fetch them. However, if you have an OU Campus page that fetches and displays a large number of MC feeds, you will see a performance increase by using cron jobs. UTC.edu’s home page fetches a number of feeds, and we saw a noticeably faster page load after moving these calls to cron jobs.

Social Media Streams

UTC uses a jQuery plugin and PHP to pull in social media posts for the university account, as well as for individual departments and colleges. This is an easy way to create a social stream sidebar or social wall page.

Facebook, Twitter and Instagram require PHP  API script for connection to signed apps. jquery.imagesloaded is helpful for the wall display

Code Samples

(A compilation zip including all code mentioned in the presentation is available. Comment and subscribe to this post to be notified of updates.)

  • WordPress plugin to add media attachments to RSS feed
  • WordPress functions.php changes
  • PHP files to parse feeds and display HTML
  • OU Campus Assets to specify RSS source and set number of posts
  • cron job to fetch RSS feeds to local server

The post Integrating Content from External Sources into OU Campus Using RSS, PHP, and JavaScript appeared first on Chris Gilligan » new media.

]]>
https://chrisgilligan.com/consulting/integrating-content-from-external-sources-into-ou-campus-using-rss-php-and-javascript/feed/ 0
TEDx Event Website https://chrisgilligan.com/portfolio/tedx-event-website/ https://chrisgilligan.com/portfolio/tedx-event-website/#respond Wed, 04 Nov 2015 17:13:14 +0000 https://chrisgilligan.com/?p=2342 I’m very excited to help out with Chattanooga’s premier TEDx event: TEDxChattanooga. For this site, I chose a responsive Bootstrap 3 SASS WordPress theme, originally developed for TEDxToronto. I made a few tweaks and improvements to better fit our event, and worked with April Cox from UT Chattanooga to dial in the design and architecture. Developed on […]

The post TEDx Event Website appeared first on Chris Gilligan » new media.

]]>

I’m very excited to help out with Chattanooga’s premier TEDx event: TEDxChattanooga.

TEDxChattanooga website screenshot

TEDxChattanooga website

screen-shot 2015-11-04 at 11.51.25 AMFor this site, I chose a responsive Bootstrap 3 SASS WordPress theme, originally developed for TEDxToronto. I made a few tweaks and improvements to better fit our event, and worked with April Cox from UT Chattanooga to dial in the design and architecture. Developed on an Amazon EC2+Ubuntu+Webmin server running a Nginx+MySQL+PHP-FPM stack, the site should handle plenty of traffic, and can be scaled up to meet spikes in demand coinciding with the event.

Please check out TEDxChattanooga.com!

Love Open Source software, but hate the generic branding? No problem. It’s very simple to create a fully-branded login screen for WordPress and Webmin/Virtualmin, to match a client’s logo and color scheme.


 

screen-shot 2015-11-04 at 11.49.19 AM

screen-shot 2015-11-04 at 12.06.49 PM

screen-shot 2015-11-04 at 12.09.52 PM

The post TEDx Event Website appeared first on Chris Gilligan » new media.

]]>
https://chrisgilligan.com/portfolio/tedx-event-website/feed/ 0
WordPress Fail2Ban RegEx for RedHat, CentOS, Amazon Linux https://chrisgilligan.com/consulting/wordpress-wp-fail2ban-regex-redhat-centos-amazon-linux/ https://chrisgilligan.com/consulting/wordpress-wp-fail2ban-regex-redhat-centos-amazon-linux/#respond Thu, 30 May 2013 00:30:24 +0000 https://chrisgilligan.com/?p=1875 VacantServer WordPress sites are getting hammered with bad logins and probes. We’ve implemented a plugin to log failed login attempts to syslog, and a Fail2Ban filter for the same. If you run these on RedHat, you’ll need some additional configuration info… here it is: WordPress login failure regex (error_log): ^%(__prefix_line)sAuthentication failure for .* from <HOST>$ […]

The post WordPress Fail2Ban RegEx for RedHat, CentOS, Amazon Linux appeared first on Chris Gilligan » new media.

]]>
VacantServer WordPress sites are getting hammered with bad logins and probes.

We’ve implemented a plugin to log failed login attempts to syslog, and a Fail2Ban filter for the same. If you run these on RedHat, you’ll need some additional configuration info… here it is:

WordPress login failure regex (error_log):
^%(__prefix_line)sAuthentication failure for .* from <HOST>$

Apache nohome regex (error_log):

[[]client <HOST>[]] File does not exist: .*/~.*

PHP noscript regex (/home/*/logs/error_log,/var/log/httpd/error_log):

[[]client <HOST>[]] (File does not exist|script not found or unable to stat): /\S*(\.php|\.asp|\.exe|\.pl)
[[]client <HOST>[]] script '/\S*(\.php|\.asp|\.exe|\.pl)\S*' not found or unable to stat *$

XMLRPC flood attacks — DDoS and probing (/home/*/logs/access_log):

<HOST>\s.*\s.POST\s/xmlrpc.php*.\s.*

Please also enable the generic apache-nohome, apache-noscript. Install wp fail2ban plugin (and configure it for your server) on your high traffic blogs. These all are helping during the current onslaught, which also includes probing for wp-admin directories, probing for /wp-admin/login.php, plus comment spam.

A new XMLRPC exploit has the script kiddies doing DDoS and probing for vulnerable services, and possibly doing remote code execution on vulnerable services.

Here are some additional resources:

The post WordPress Fail2Ban RegEx for RedHat, CentOS, Amazon Linux appeared first on Chris Gilligan » new media.

]]>
https://chrisgilligan.com/consulting/wordpress-wp-fail2ban-regex-redhat-centos-amazon-linux/feed/ 0
Auto Mailer Form with Validation and reCAPTCHA https://chrisgilligan.com/forms/auto-mailer-form-with-validation-and-recaptcha/ https://chrisgilligan.com/forms/auto-mailer-form-with-validation-and-recaptcha/#comments Wed, 16 Jan 2013 21:51:06 +0000 https://chrisgilligan.com/?p=1566 I was recently searching for a form template that uses Twitter’s Bootstrap framework. PFBC, the PHP Form Builder Class, was recently refactored with Bootstrap, and it also supports validation and reCAPTCHA. PFBC does not include a form handler, but it does take the difficult and redundant work out of creating self-validating forms. Adding an auto-mailer […]

The post Auto Mailer Form with Validation and reCAPTCHA appeared first on Chris Gilligan » new media.

]]>

Screen Shot 2013-01-16 at 4.19.03 PMI was recently searching for a form template that uses Twitter’s Bootstrap framework. PFBC, the PHP Form Builder Class, was recently refactored with Bootstrap, and it also supports validation and reCAPTCHA. PFBC does not include a form handler, but it does take the difficult and redundant work out of creating self-validating forms.

Adding an auto-mailer to PFBC is very simple, however. You just need a simple PHP if/else and all is well.

If you have read this far, you should go ahead and download PFBC version 3 (with Bootstrap). You’ll want to install it on a dev server and read the documentation, which is on the example pages. Installation: put the downloaded folder in a public_html space that’s running PHP 5+.

Note that there are different packages for PHP 5.3, so get the correct flavor of version 3. This example works with PHP 5.3.

I have created an example form that includes most of the different types of inputs, all you need do is create a file in the same folder as the package’s main index.php. I’ve heavily commented the code, so you should be able to easily understand it.

<?php
// php-form-builder-class PFBC 
// set up name spaces for form, elements, and validation
use PFBC\Form;
use PFBC\Element;
use PFBC\Validation;

session_start();
error_reporting(E_ALL);
include("PFBC/Form.php");

include("header.php");
$version = file_get_contents("version");

// has the form been submitted and passed validation? 
// If so, send email and display a confirmation message.
if(Form::isValid($_POST["form"])) {
    /*The form's submitted data has been validated.  Your script can now proceed with any 
    further processing required.*/

  //get the POST data from the form
  $Course 				= $_POST['Course'];
  $Semester 			= $_POST['Semester'];
  $WhyUnavailable 		= $_POST['WhyUnavailable'];
  $DetailUnavailable 	= $_POST['DetailUnavailable'];
  $Classification 		= $_POST['Classification'];
  $Major 				= $_POST['Major'];
  $Email 				= $_POST['Email'];
  $Comments 			= $_POST['Comments'];
  // loop through the When field's checkbox group and output them all with a return between values
  foreach ($_POST['When'] as $val) { 
  $When .= $val."\n";
	}
  $DetailWhen 			= $_POST['DetailWhen'];

 	// create and send the email
	$to 			= "you@yourdomain.com";

    $email_from 	= $Email;

    $email_subject 	= "Course Request: $Course, $Semester, $When";

    $email_body 	= 	"Course: $Course\n\n".
						"Semester: $Semester\n\n".
						"Why: $WhyUnavailable\n$DetailUnavailable\n\n".
						"Classification: $Classification\n".
						"Major: $Major\n\n".
						"Email: $Email\n\n".
						"Comments: $Comments\n\n".
						"When offered:\n$When".
						"$DetailWhen\n\n";

	$headers		= "From: $email_from \r\n".
					  "Reply-To: $email_from \r\n";

	mail($to,$email_subject,$email_body,$headers);

		echo "			<div class=\"alert alert-success\">
				<a class=\"close\" data-dismiss=\"alert\" href=\"#\">×</a>
				<strong class=\"alert-heading\"> Thank you for submitting a course Course Request. By providing this feedback you will help us to make adjustments to the schedule both now and in the future.</strong>
			</div>";

 }//end if(Form::isValid

// is the form loaded for the first time, or does input need to be entered or corrected?
// if so, display the form. Validation prompts are displayed by the form itself.
else {
    header("Location: " . $_SERVER["PHP_SELF"]);
    /*Validation errors have been found.  We now need to redirect back to the 
    script where the form exists so the errors can be corrected and the form
    re-submitted.*/

echo "<h1>What course do you need?</h1>
<p>We are committed to doing all we can to help you graduate in as timely a fashion as possible. We know that sometimes, as you arrange your schedule for the upcoming semester, you are unable to find an available seat in a course that you need. Whenever possible we aim to be responsive to students' needs. By providing this feedback you will help us to make adjustments to the schedule both now and in the future.</p>
<div class=\"alert alert-warning\">
				<a class=\"close\" data-dismiss=\"alert\" href=\"#\">×</a>
				<strong class=\"alert-heading\">* denotes required fields.</strong>
			</div>";

// The form identifier
$form = new Form("CourseNeed");
// Prevent bootstrap and jquery from re-loading, already loaded in doc head
$form->configure(array(
	"prevent" => array("bootstrap", "jQuery")
));
// Validation field for feedback messages to user
$form->addElement(new Element\Hidden("form", "CourseNeed"));
// Form fields
// simple textbox, required
$form->addElement(new Element\Textbox("Course:", "Course", array(
	"required" => 1,
	"shortDesc" => "Department and course number of class you need",
	//"placeholder" => "MATH 101"
)));
// simple select, required
$form->addElement(new Element\Select("Semester:", "Semester", array( // first array is the options
	"",// blank value to force a choice
	"Fall",
	"Spring",
	"Summer I",
	"Summer II",
	),
	array( // second array is the parameters
	"Required" => 1, // required to force a choice
	"shortDesc" => "Choose One&hellip;"
)));
// simple select, required
$form->addElement(new Element\Select("Why Unavailable:", "WhyUnavailable", array( // first array is the options
	"",// blank value to force a choice
	"All the scheduled spots are full",
	"All available classes conflict with my schedule",
	"The course is not being offered in that semester",
	"Other",
	),
	array( // second array is the parameters
	"Required" => 1, // required to force a choice
	"shortDesc" => "Choose One&hellip; Why is the course unavailable to you?"
)));
$form->addElement(new Element\Textbox("Details:", "DetailUnavailable", array(
	"shortDesc" => "If 'Other': Why is the course unavailable to you?"
	)));
// simple select, required
$form->addElement(new Element\Select("Your Classification:", "Classification", array( // first array is the options
	"",// blank value to force a choice
	"Freshman",
	"Sophomore",
	"Junior",
	"Senior",
	"Graduate",
	),
	array( // second array is the parameters
	"Required" => 1, // required to force a choice
	"shortDesc" => "Choose Your Classsification&hellip;"
)));
$form->addElement(new Element\Textbox("Major:", "Major", array(
	"required" => 1,
	"shortDesc" => "Your Major"
)));
// email, self-validating, required
$form->addElement(new Element\Email("Email:", "Email", array(
	"Required" => 1,
	"shortDesc" => "Preferably, a university email address",
	"placeholder" => "you@domain.com"
)));
// simple textarea
$form->addElement(new Element\Textarea("Comments:", "Comments", array(
	"placeholder" => "Optional: additional information that may explain your situation or your needs."
)));
// simple checkbox set
$form->addElement(new Element\Checkbox("When:", "When", array( // first array is the options
	"Morning",
	"Afternoon",
	"Evening",
	"Online",
	"Other",
	),
	array( // second array is the parameters
	"Required" => 1, // required to force a choice
	"shortDesc" => "Please choose time(s) when would you like the course offered&hellip;"
)));
$form->addElement(new Element\Textbox("Details:", "DetailWhen", array(
	"shortDesc" => "If 'Other': When would you like the course offered?"
	)));
// reCAPTCHA with validation, automaticallly required
$form->addElement(new Element\Captcha("Validation:", array(
	"longDesc" => "This is a <a href=\"http://en.wikipedia.org/wiki/ReCAPTCHA\">
	reCaptcha test</a> to reduce spam submissions."
)));
// submit button and cancel button
$form->addElement(new Element\Button);
$form->addElement(new Element\Button("Cancel", "button", array(
	"onclick" => "history.go(-1);"
)));
// draw the form
$form->render();
}//end else

If you want to implement a form on a site that does not include Twitter Bootstrap, you may find the bootstrap.css conflicts with many of your site’s styling.

In that case, you can go to Bootstrap’s Customize and Download page, and choose only the css, js and components you need:

Scaffolding
none

Base CSS
Forms, Buttons

Components
Button groups, Alerts

JS Components
Collapse

Miscellaneous
Close icon

Utilities
Component animations

Responsive
none

The post Auto Mailer Form with Validation and reCAPTCHA appeared first on Chris Gilligan » new media.

]]>
https://chrisgilligan.com/forms/auto-mailer-form-with-validation-and-recaptcha/feed/ 2