Cookbook

The Cookbook is a collection of real world examples and tutorials of how you can use Zoop.

Integrating Zoop and Drupal
Here Zoop community member Jeremy will be walking us through how he integrated Zoop and Drupal. This tutorial will be created Wiki style in hopes that others will aid / update.

FTP Component

I wrote the FTP component to allow for an easy way of uploading files via FTP. This component is easily extensible.

1. Install Pear package Net_ftp or copy the files to your libs directory.

2. Create a config file ftp.php in your config directory for any possible defines.

3. Make a directory FTP in your Zoop installation. Please include the following files:
/*************************
***** ftp_component.php **
*************************/
<?php
/**
* FTP component - Component allows for transferring files using the PEAR package Net_FTP
*
* Copyright (c) 2009 Jayesh Wadhwani, Dominion Enterprises
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* If you have any questions or comments, please email:
* Jayesh Wadhwani
* jayesh.wadhwani@dominionenterprises.com
* http://www.dominionenterprises.com/
*
*
* PHP versions 5
*
* * component_ftp
*
* Please make sure that you have the Pear package Net_FTP installed on your system.
* Alternately you could also download the files and put them in your libs folder.
* @uses component
* @package
* @version $id$
* @copyright 2009 Dominion Enterprises
* @author Jayesh Wadhwani
*/
class component_ftp extends component
{
function component_ftp()
{

}

function getIncludes()
{
return array(
"ftp" => $this->getBasePath() . "/ftp.php"
);
}
}
?>
/*************************
******** ftp.php *********
*************************/
<?php
require_once 'FTP.php';
/**
* A wrapper for the Net_ftp Pear package
*
* The most common application for FTP is to connect and send a file. This is what I
* have implemented. You can extend this class for more functionality.
*
* @author Jayesh Wadhwani
* @copyright 2009 Dominion Enterprises
* @license http://www.gnu.org/copyleft/gpl.html GPL License 2 or later
*/
class ftp
{

//The FTP handle
private $ftp;

//login credentials
private $username;
private $password;

/**
* Instantiation of class and setup
*
* @param string $host e.g. somehost.mysite.com
* @param int $port e.g. 21 default is 21
* @param string $username e.g. somehost.mysite.com
* @access public
*/
function __construct($host, $port = 21, $username, $password){
$this->username = $username;
$this->password = $password;
$this->ftp = new Net_FTP($host, $port);
}

/**
* Use this to upload a file to the host server
*
* @param string $sourceFile
* @param string $destinationFile
* @param bool $overwrite - a value of true will overwrite the destination file.
* @param int $transferMode - FTP_ASCII or FTP_BINARY. Default is FTP_ASCII
* @param int $transferMode - FTP_ASCII or FTP_BINARY. Default is FTP_ASCII
* @access public
*/
function ftpUpload($sourceFile, $destinationFile, $overwrite = true, $transferMode = FTP_ASCII, $passive = true){

//make the connection
$result = $this->ftp->connect();

if (PEAR::isError($result)){
print $result;
}

//login
$result = $this->ftp->login($this->username, $this->password);

if (PEAR::isError($result)){
print $result;
}

//set connection type
if($passive === true){
$this->ftp->setPassive();
}

//upload
$result = $this->ftp->put($sourceFile, $destinationFile, $overwrite, $transferMode);

if (PEAR::isError($result)){
print $result;
}
}

/**
* Close connection on exit
* @access public
*/
function __destruct(){
$this->ftp->disconnect();
}

}

/***************************
*** defaultConstants.php ***
***************************/

<?php

?>
/***************************
*** Example: ***************
***************************/
<?php
$sourceFileName = '/www/files/source.xml';
$destination = '/public_html/destination.xml';

$b = new ftp('somehost.somesite.com', 21, 'username', 'password');
$b->ftpUpload($sourceFileName, $destination, true, FTP_BINARY);

?>

Integrating Zoop and Drupal

Here Zoop community member Jeremy will be walking us through how he integrated Zoop and Drupal. This tutorial will be created Wiki style in hopes that others will aid / update.

Objective
The purpose of this tutorial is to show you how to add a Zoop (1.3) application or page to Drupal 5 as a content page. These techniques will probably work in Drupal 4 but the function names are different. Additionally, I will explain how to integrate session management from Drupal into Zoop. The latter opens up the entire scope of user/session/subscription management modules to your Zoop app. ..Yes, you read that correctly. **I have not tested any of this with Zoop 1.5**

Adding your Zoop application or page to Drupal

  1. Create a new page in Druapl. Set the input mode on the page to be php
  2. Add you content like so. You must use the functions in the sample to add css and js to you page. The function calls will be executed before the page loads and the files you load will appear in the head tag of the Drupal page. So, don't expect execution of and scripts in the body. If you want execution when the page loads you need to add an onload in one of the js files you load. That's what I did ...keep reading. Alternatively, there's supposed to be a "correct" way to create an onload in Drupal. I don't know what that is.

    Nothing is written in stone reagarding what to include and what to exclude. I have no HTML in my pages other then a single div with an id attribute since my Zoop app is 100% Ajax.

    <div id="myContentDiv"></div>

  3. This example sets a body onload event that will trigger an Ajax call using Prototypes Upater method. The returned content fills the div. From there the application is visible to the user. I happen to have a smarty template that loads a set of four divs into along with other application content. I use those four divs to display additional messages, content, status information and whatever else I want.

    The myapp.js file contains this along with the entire application.

    embed = MyApp;
    window.onload=function(){
      if(embed){
         loadEmbed('Embed' + embed,'myContentDiv','myZone');
      }else{
         alert('Error: No content specified for loading'); 
      }
    }
    loadEmbed = function(what,where,zone){
      var url='/skeleton/index.php/' + zone + '/' + what;
      new Ajax.Updater(where,url,{method: 'get', onComplete: function(transport){initApp();}
                                               });
    }

    This js loads the content returned from /skeleton/index.php/myZone/EmbedMyApp/ in to myContentDiv and onComplete it runs initApp(). initApp() just sets some defaults on the page.

  4. If you are not using AJAX just load the Zoop components you need in to the page. Remember that submitting the page will submit to the Drupal URL, not the Zoop URL. Thus, you cannot expect zoop behavior. However, you could probably create other pages in Drupal to handle you posts. After all Drupal accepts PHP content. Really, AJAX is so easy with Zoop and Prototype. Why would you not use it.
  5. save you page and test it.

Integrating Zoop and Drupal session and user management

Before I start, know that I've been using this scenario on a large application for going on 9 months with absolutely no ill effects.

...Your mileage may vary and I may have left something out unintentionally (Though I'm pretty sure I didn't).

Are you ready?
Go get something to eat and a pot of coffee, this could take days! ;-)

  1. Locate Your Drupal includes/bootstrap.inc file. (yes, Drupal needs to be installed already).
    Take note of the path to that file.
  2. Open the file session/session_component.php in your Zoop source directory. (yes, Zoop needs to be installed already)
  3. change the name of the init function to something else. I renamed mine '_init'. You might prefer 'original_init' or 'mydoghasfleas'.
  4. Paste in this shiny new init function. Make sure you replace 'your_drupal_bootstrap_path' with the path you took note of above. Make sure it's the full path to the bootstrap.inc file.

function init()
{
    require_once 'your_drupal_bootstrap_path';
    drupal_bootstrap(DRUPAL_SESSION_DATA_ONLY);
}

  • Your done.
  • Testing and Using your Drupal - Zoop Integration

    Assuming everything was done correctly with the bootstrap integration above you're ready to use drupal and zoop together.

    Here's a way to have your Zoop app depend on Drupal for permissions,user management, sessions, etc.

    1. Open up the zone file for your zoop app.
    2. In your initZone file use something like this condition to control whatever you want to control.

     $user = $GLOBALS['user'];  //This is one of the globals that Drupal creates.
     //print_r($user);  // Do this to see what you have access to.
     if($user->uid > '1'){
         if( $user->roles[4] == 'Premium Subscriber' || $user->roles[6] == 'Some Role'){
              define_paying_subscriber_globals(); // A function that does stuff for these people.
         }else{
              // Unauthenticated user - must login via drupal
              print "The Section is for paying subscribers only.<br/>";
              exit;
         }
     }else if($user->uid == '0'){
         print "You are not logged in.<br/>";
         exit;
     }

  • You can access this page outside drupal or you can integrate Ajax calls to this page in your drupal page (that's what I do). The latter is detailed on this page.
  • Now you can build your site using all the user and group management possibilities of Drupal and use zoop to build the core application. In my case, I use premium content and roles in Drupal to control what parts of the application my users can access. There is no need to limit yourself to the initZone function. You can access the drupal globals from anywhere you want.

    gotchas with Drupal:

    1. Drupal templates can change the layout of your zoop generated content. This is often a very good thing. However, it can be a real pain when using various selector widgets that have their own styles. This is generally because some templates are designed to enforce styles globally. So, you'll find css constructs for things like div,th,td,table ...etc that will affect any such elements on the page. If you care, you should modify the template css or your code accordingly.

    Go create something,
    Jeremy Brooks

    Quick Start Guide

    Pre-Reqs

    Before attempting to install the Zoop framework, please make sure you have a recent version of PHP installed (minimum PHP 4.4.8+, we recommend the most recent stable version of PHP 5) and working both from the command line and with a web server.

    Steps

    1. Download the Zoop Framework and unpack it anywhere. We recommend a good conventional shared location -- perhaps /usr/local/, which we'll use in the rest of this example -- but any location will do. Users testing the framework on shared hosting may choose to put it under their home directory.
    2. Open a command shell. Within any web-available directory in which you wish to create your new application, type the following:  
    3. php /usr/local/zoop/zoop_create.php project hello
      (Or, if you've placed zoop elsewhere: php /your/path/to/zoop/zoop_create.php project hello )

    Check the directory listing after the script runs succesfully. You should see a folder/directory named "hello."

  • Open the directory "hello." Upon viewing a directory listing, you should see:
    	GuiControls	config		includes.php	objects		tmp
    	GuiWidgets	config.php	index.php	public		zones
    	classes		guiplugins	mail		templates
  • Open the file "config.php". Look for a line that begins with:

    define('zoop_dir','/usr/local/zoop')

    Change this line to make sure that the second argument of this define statement is the same as the location you installed zoop. Save the file and exit.

  • Open the file "zones/default.php". Look for a method named "pageDefault" inside. Edit this method so that it reads:

        function pageDefault($inPath) {
            echo("Hello world!");
        }

  • Now we're ready to make our first request to our new zoop application. Within a web browser, go to:

    http://yourhost.com/path/to/hello/

    You should see the output "Hello world!"

  • Let's make our little app slightly more personalized. Open the file "zones/default.php" again. After the "pageDefault" method, create a new method:

    	function pageByName($inPath) {
    		$name = isset($inPath[1]) &amp;&amp; !empty($inPath[1]) ? $inPath[1] : 'no name';
    		echo("Hello $name!");
    	}

  • Now check the results within your web browser by going to:

    http://yourhost.com/path/to/hello/index.php/ByName/YourName

    You should see the output "Hello YourName!"

  • Screencast - Zoop First Application in Ten Minutes (Windows)

    How to install Xampp, Zoop and make a simple Hello World.
    You can see Zoop power to speed and organize your PHP programming.

    First App In Ten Minutes

    Screencast: Building a PHP contact form with the Zoop Framework

    And here are the code snippets I used in this screencast:

    pageDefault

    	/**
    	 * pageDefault
    	 *
    	 * @param mixed $inPath
    	 * @access public
    	 * @return void
    	 */
    	function pageDefault($inPath)
    	{
    	// 	You may usually want the following line, but for our demo we don't
    	// 	$this->zoneRedirect("login");
     
     		global $sGlobals;
     		global $gui;
     
     		//this is for gets.  It displays the page
     		$gui->display("contact-form.tpl");
    	}

    postDefault

    	/**
    	 * postDefault
    	 *
    	 * @param mixed $inPath
    	 * @access public
    	 * @return void
    	 */
    	function postDefault($inPath)
    	{
    		global $sGlobals, $gui;
    		//this is for posts, it handles when forms get submitted.
     
    		$post = getPost();
     
    		$from = $post['address'];
    		$to = 'justin@mailinator.com';
    		$cc = null;
    		$subject = $post['subject'];
    		$body = $post['message'];
     
    		$msg = new message();
    		$msg->sendTextEmail($from, $to, $cc, $subject, $body);
     
    		$gui->assign('message', 'Thanks for contacting us!');
    		$gui->display('message.tpl');
    	}

    Note: It's not a good practice to actually display things in the post handlers. As a general rule, you should do your emailing and form handling in the post handler, then redirect to a page function to display feedback. Something like this:

    	/**
    	 * postDefault
    	 *
    	 * @param mixed $inPath
    	 * @access public
    	 * @return void
    	 */
    	function postDefault($inPath)
    	{
    		global $sGlobals;
    		//this is for posts, it handles when forms get submitted.
     
    		$post = getPost();
     
    		$from = $post['address'];
    		$to = 'justin@mailinator.com';
    		$cc = null;
    		$subject = $post['subject'];
    		$body = $post['message'];
     
    		$msg = new message();
    		$msg->sendTextEmail($from, $to, $cc, $subject, $body);
     
    		zoneRedirect('thanks');
    	}
     
    	/**
    	 * pageThanks
    	 *
    	 * @param mixed $inPath
    	 * @access public
    	 * @return void
    	 */
    	function pageThanks($inPath)
    	{
    		global $sGlobals, $gui;
    		$gui->assign('message', 'Thanks for contacting us!');
    		$gui->display('message.tpl');
    	}

    Contact form template

    {include file="head.tpl"}
    <body>
     
    <h1>Contact Me!</h1>
     
    <p>Fill out the form below to contact me.</p>
     
    <form method="POST">
     
    	<div>
    		<label for="name">Name:</label>
    		<input name="name" id="name" type="text" />
    	</div>
     
    	<div>
    		<label for="address">Email address:</label>
    		<input name="address" id="address" type="text" />
    	</div>
     
    	<div>
    		<label for="subject">Subject:</label>
    		<input name="subject" id="subject" type="text" />
    	</div>
     
    	<div>
    		<label for="message">Message:</label>
    		<textarea name="message" id="message"></textarea>
    	</div>
     
    	<input type="submit" name="submit" value="Send Message" />
    </form>
     
    </body></html>