Textile Behavior

This Behavior is based on the article in the Bakery and the version posted in comments by Adeel Khan.

To use this behavior you need classTextile.php from TextPattern subversion repository. Put it in one of the vendor dirs (/vendor or /app/vendor).

To use it add

var $actAs = array('Textile');

in your model. By default it expects to find a field named body that will contain the textile formated text and html_body that will contain html generated by textile. Here are the default options:

var $actAs = array('Textile' => array('body' => array(
					'html_prefix' => 'html_',
					'rel' => '',
					'lite' => false, 
					'noimages' => false,
					'restricted' => false))
);

Here is a good explanation about different modes that Textile parser can work in by Alex from TextPattern forums(emphasis mine).

Textile Lite allows bq and p, but no other block tags. It doesn’t prevent raw XHTML by itself.
Textile Restricted escapes all raw HTML and special characters and turns off class/id/style/lang attributes, to prevent certain types of XSS attacks from untrusted users (it’s intended for comment forms, forum posts etc). It also uses ‘rel=nofollow’ on external links by default, but you can control that via the function parameters.
Both the normal (TextileThis()) and restricted (TextileRestricted()) functions can be used with or without Lite mode. I believe the Textpattern support forum uses Textile Restricted without Lite. I’d suggest:
* TextileThis with Lite=0 for article content from trusted users
* TextileRestricted with Lite=0 for article content, forum posts and larger content from untrusted users
* TextileRestricted with Lite=1 for comment posts, short descriptions etc
* TextileThis with Lite=1 is probably not very useful

You can have multiple fields per model that will be textiled ;)

var $actAs = array('Textile' => array('body', 'excerpt' => array(
					'html_prefix' => 'html_',
					'rel' => 'nofollow',
					'lite' =>true, 
					'noimages' => true,
					'restricted' => true))
);

The body here will have the default options and the excerpt wont allow html or images and link will have the 'bofollow' attribute.

Source code

Here is the code - save it to app/models/behaviors/textile.php

<?php
/**
* Textile Behavior
*
* this is a Textile behavior based on the work of Adeel Khan and Walker Hamilton 
*
* PHP versions 4 and 5
*
* Copyright (c) Marcin Domanski http://kabturek.info/
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright      Copyright (c) 2007, Marcin Domanski.
* @link            http://wiki.kabturek.info/textile_behavior
* @link            http://kabturek.info/
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
*/
vendor('classTextile');
class TextileBehavior extends ModelBehavior 
{
	/**
	* the actual model
	*
	* @var object
	*/
	var $model;
 
	/**
	* fields
	*
	* @var array
	*/
	var $fields = array();
 
	/**
	* setups the behavior
	*
	* @param object &$model the model that the behavior is called from 
	* @param array $settings the settings array defined in the model
	*/
	function setup(&$model, $settings = array()) 
	{
		$this->model =& $model;
		$default = array( 'body' => array('html_prefix' => 'html_',
					'rel' => '', 
					'lite' => false,
					'noimages' => false, 
					'restricted' => false) 
		);
 
		if (empty($settings)) 
		{
				$this->fields = $default;
		}
		else
		{
			$this->fields = $settings;
		}
		foreach($this->fields as $field => $options)
		{
			$htmlPrefix = 'html_';
			if(!empty($options['html_prefix']))
			{
				$htmlPrefix = $options['html_prefix'];
			}
			if(false===$model->hasField($field))
			{
					user_error('Model "'.$model->name.'" does not have a field called: '. $field, E_USER_ERROR );
			} 
			else if(false===$model->hasField($htmlPrefix.$field)) 
			{
					user_error('Model "'.$model->name.'" does not have a field called: html_'.$field, E_USER_ERROR );
			}
		}
	}
 
	/**
	* beforeSave callback
	*
	*/
	function beforeSave() 
	{
		$textile = @new Textile;
		foreach($this->fields as $field => $options)
		{
			if(isset($this->model->data[$this->model->name][$field]))
			{
				$rel ='';
				$lite = 0;
				$noimages = 0;
				$htmlPrefix = 'html_';
 
				if(!empty($options['rel']))
				{
					$rel = $options['rel'];
				}
				if(isset($options['lite']) && $options['lite'] == true)
				{
					$lite = 1;
				}
				if(isset($options['noimages']) && $options['noimages'] == true)
				{
					$noimages = 1;
				}
				if(!empty($options['html_prefix']))
				{
					$htmlPrefix = $options['html_prefix'];
				}
 
				if(isset($options['restricted']) && $options['restricted'] == true)
				{
					$this->model->data[$this->model->name][$htmlPrefix.$field] = @$textile->TextileRestricted($this->model->data[$this->model->name][$field], $lite, $noimages, $rel);
				}
				else
				{
					$this->model->data[$this->model->name][$htmlPrefix.$field] = @$textile->TextileThis($this->model->data[$this->model->name][$field], $lite, '', $noimages, '', $rel);
				}
			}
		}
    return parent::beforeSave($this->model); 
	}
}
?>

Textile Reference

Here is a handy Textile reference.

Marcin Domanski 2007/07/27 01:46

~~DISCUSSION~~

 
textile_behavior.txt · Last modified: 2007/09/13 21:19 (external edit)
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki