Blog

2007 06 posts (20)

Pages: < Previous 1–10 11–20 Next >
Ordering: Ascending Descending

1. DIY tips: Form refill

2007-06-30 15:05:19 by Martynas Jusevičius

Developing with HTML forms, there is often a need to refill input fields with previously entered user data, e. g. when the user tries to submit the form, but some data is not valid and has to be corrected (and therefore the form has to be displayed again).

Here's how you can do it using the DIY Framework. First, in the Resource subclass that handles the form submission, you need to have the appropriate Form object created. And in most cases, you have it already, since it is used to access the submitted data (i. e. the request parameters) conveniently. For example, we create a CommentForm in our PostResource when there is a comment submitted:

$form = new CommentForm($request);

Then, you most likely validate the form by calling its validate() method and based on that result (or possibly other factors as well) decide if the submission request was successful and user data is to be saved or otherwise processed (e.g. the required comment fields are filled and the comment will be saved), or there was an error (e. g. authors name is missing in the comment) and the same View with the form has to be displayed again, only with the input fields refilled this time:

$errors = $form->validate();

Knowing that, we set the Request result attribute either as success or as failure:

$request->setAttribute("comment-result", "success");

Then, the final thing the resource has to do is to set the form object as a request attribute as well. To be able to determine later which errors caused the failure of submission, we also set the errors array:

$request->setAttribute("comment-form", $form);
$request->setAttribute("comment-errors", $errors);

The rest of the logic is handled by the View. It has has to set the appropriate form parameters and arguments if there was a submission attempt:

if ($request->getAttribute("comment-result") != null)
{
	$this->proc->setParameter("", "comment-result", $request->getAttribute("comment-result"));
	$this->resolver->setArgument("comment-errors", XMLSerializer::serialize($request->getAttribute("comment-errors")));
	$this->resolver->setArgument("comment-form", XMLSerializer::serialize($request->getAttribute("comment-form")));
}

And then, the XSLT template is where the actual “refilling” takes place. If the $comment-result (which has to be a top-level parameter in the stylesheet) is a failure, then the input field gets the value from the serialized Form (if there was any):

<input type="text" id="name" name="name" maxlength="40">
	<xsl:if test="$comment-result = 'failure'">
		<xsl:if test="document('arg://comment-form')//Name">
			<xsl:attribute name="value"><xsl:value-of select="document('arg://comment-form')//Name"/></xsl:attribute>
		</xsl:if>
	</xsl:if>
</input>

Add a comment Comments (323)

2. Typography on the Web

2007-06-22 21:40:57 by Martynas Jusevičius

In the digital era that we live in, computers and the Web have pretty advanced typesetting features with the help of vector fonts and standards like XML and Unicode. However, many people use them with an old-school typewriter-mindset, or maybe they're just being ignorant. That is why you can find examples of weird and wrong typography like -- imitating an M-dash (—) or ,,'' imitating quotes.

We try to use correct typography and encourage you to do so. There are more characters to use than a hyphen and one type of quotes. This table shows the most useful ones:

Character Name Named entity Decimal entity Common use
- Hyphen-minus &#45; Joins words; Separates syllables
N-dash &ndash; &#8211; Indicates a range
M-dash &mdash; &#8212; Indicates a break in a sentence
Hyphen &#8208; Joins words; Separates syllables
Minus &minus; &#8722; Mathematical expressions
Left double quotation mark &ldquo; &#8220; Quotations
Right double quotation mark &rdquo; &#8221; Quotations
Left single quotation mark &lsquo; &#8216; Quotations
Right single quotation mark &rsquo; &#8217; Quotations

For broader explanation, see a useful article The Trouble With EM ’n EN (and Other Shady Characters) on A List Apart.

Add a comment

3. (X)HTML embedded in RSS

2007-06-20 20:15:19 by Martynas Jusevičius

Can anybody show a working example of XHTML embedded in RSS 1.0? We've seen it done in RSS 2.0 and Atom, but not RSS 1.0.

We know one can put escaped HTML markup into the feed and the readers would understand it. But we do not do it on purpose, because escaped HTML is harmful. As an example of that, some RSS readers try to interpret our escaped markup which is actually sample code for XML or XSLT and should not be interpreted at all. We generate valid XHTML, so escaping it before embedding into another XML format makes no sense.

Or should we switch to Atom? But what we like about RSS 1.0 is that it is based on RDF :)

Add a comment Comments (1)

4. A rule for writing secure PHP applications

2007-06-18 14:07:55 by Martynas Jusevičius

One of the hottest topics in PHP is security. Hundreds of recommendations, articles, tutorials, and various check-lists addressing this issue have been written.

From our experience, there is a simple yet important rule that leads to more secure (and probably generally better) Web applications:

Do not mix PHP, (X)HTML, and/or SQL code together!

That will “automagically” protect you from the most common attacks such as SQL injection.

There are several techniques that can help you:

Add a comment Comments (1)

5. Drop the old proprietary formats

2007-06-16 19:19:40 by Martynas Jusevičius

The Web standards and their support in browsers have really improved. It is now time to drop the old proprietary and binary formats and replace them with open, standard technologies.

PDF
It is a proprietary binary format. You can't open it without a third-party plugin and you can't construct or process it without special libraries or applications.
Does not look very portable after all. So why would you ever publish something on the Web in PDF? Right, it is supposed to give precise control over the layout of the document and make it print nicely. But have you checked lately what (X)HTML and CSS are capable of these days? And if you'll need graphics or formulas in your content, there is SVG and MathML. Drop PDF and go for nice and rich webages.
Microsoft Office files
Very much the same as for PDF. But if you really need to publish in some office-suite format, choose OpenDocument (ODF), which is an XML-based standard.
Flash
Like PDF, Flash is proprietary, binary, requires a plugin to play it and special software to build it. Furthermore, it breaks accessibility and navigation, is hard to use on non-Microsoft platforms, and is not indexed by search engines.
Drop Flash and switch to SVG, which is an XML-based standard, supports animations and has a programming interface. Consider SMIL as well.
Raster images
Where possible, replace your raster drawings and graphics with SVG. That will make them scalable and improve accessibility, among other things. And for other kinds of pictures, at least consider switching from GIF to PNG, which supports transparency and a wider range of color depths and is a non-proprietary standard.

Add a comment

6. DIY tips: implementing simple CAPTCHA

2007-06-12 13:10:34 by Martynas Jusevičius

CAPTCHA is a popular way to test whether the user is a human. It is widely used on the Web, for example in blogs, wikis, and webmail applications. CAPTCHA provides a pretty good protection from spambots flooding the website with comments or entries, and other kinds of bots trying to make undesired batch changes automatically. Actually, the first ever comment on our blog before implementing CAPTCHA was spam :)

The most popular form of CAPTCHA is probably the image recognition. However, it can be inaccessible for some users, and W3C suggests some other, more accessible forms of testing. We decided to implement a simple arithmetical test that asks to enter the sum of 2 random numbers displayed.

We will show how easily you can implement this form of CAPTCHA using the DIY Framework. First, you need to modify the View that displays data submission form you want to protect. In our case, that was ReadPostView. We added several lines to the PHP class:

$randNumber1 = rand(1, 9);
$randNumber2 = rand(1, 9);
$this->proc->setParameter("", "rand-number-1", $randNumber1);
$this->proc->setParameter("", "rand-number-2", $randNumber2);
$request->getSession()->setAttribute("captcha", $randNumber1 + $randNumber2);

This code generates 2 random numbers in the range [1..9] that will be used for testing. Then, these numbers are passed to the XSLT template and their sum, i. e. the CAPTCHA test value, is set as a session attribute.

Changes to the XSLT code are pretty trivial. Firstly, add top-level parameters for those 2 numbers:

<xsl:param name="rand-number-1"/>
<xsl:param name="rand-number-2"/>

and then add the test field to the submission form:

<label for="captcha"><xsl:value-of select="$rand-number-1"/> + <xsl:value-of select="$rand-number-2"/> =</label>
<input type="text" id="captcha" name="captcha" maxlength="2"/>

The final thing you have to do is to add the actual check if the submitted sum was correct. In our case, comment submissions from post URLs were handled by PostResource. We added several lines to its comment handling:

if ($form->getCaptcha() != $request->getSession()->getAttribute("captcha"))
{
	$errors[] = new Error("invalidCaptcha");
	throw new Exception("Errors");
}

They check if the CAPTCHA value, i. e. the sum of 2 random numbers, is the same as submitted by the user in the CommentForm. If it is, the program flow continues and the comment is saved. Otherwise, an exception is raised, which later makes the View to display an error. You also need to handle this kind of error in the XSLT template if you want it to appear with a description (e. g. “The sum was wrong”). And, of course, as with every new form field, you need to add the test field to the CommentForm and its serialization in XMLSerializer.

That's it, a simple arithmetical CAPTCHA test was implemented! You can see how it works by commenting this post :)

Add a comment

7. Beta version of Safari for Windows released

2007-06-12 01:41:03 by Martynas Jusevičius

Today, Apple has released a public beta of Safari 3, which for the first time includes a version for Windows. It is now claimed to be the fastest browser on the market.

Official Safari website

Add a comment

8. Denmark's national broadcaster digitizes archives

2007-06-11 14:16:47 by Martynas Jusevičius

DR (Danmarks Radio), Denmark's national TV, radio, and online broadcaster, has announced a few days ago that it will digitize its archives and make them available for public.

A part of archives will be opened from January 1st, 2008. Before that, people will be able to express their wishes on the broadcaster's website as to what shows should be digitized first from the 30-kilometer-long shelves. Examples include children programs, drama classics, and documentaries. DR plans launch of custom, specialized digital TV and radio channels based on the archival content.

According to DR, it is the first decision of this kind in the world. With the help of new technologies, it is going to make access to nation's cultural heritage easier. However, there was no promise that the access will be totally open and unrestricted.

Official press release (in Danish)

Add a comment

9. DIY tips: implementing search with Propel

2007-06-10 11:27:31 by Martynas Jusevičius

Implementing search functionality on your website has never been easier. Here is how we do it with the DIY Framework and Propel:

class SearchView extends XSLTView
{
	function display(Request $request, Response $response)
	{
		$search = strip_tags($request->getAttribute("search-form")->getSearch());

		$pageForm = new PageForm($request);
		$offset = 0;
		if ($pageForm->getOffset() != null) $offset = $pageForm->getOffset();
		$limit = 10;
		if ($pageForm->getLimit() != null) $limit = $pageForm->getLimit();
		$desc = true;
		if ($pageForm->getDesc() == "false") $desc = false;
		$orderBy = 1;

		$c = new Criteria();
		$criterion = $c->getNewCriterion(PagePeer::TITLE, "%".$search."%", Criteria::LIKE);
		$criterion->addOr($c->getNewCriterion(PagePeer::CONTENT, "%".$search."%", Criteria::LIKE));
		$c->add($criterion);

		$pageCount = PagePeer::doCount($c);

		$c->setLimit($limit);
		$c->setOffset($offset);
		if ($desc)
		{
			$c->addDescendingOrderByColumn(PagePeer::DATETIME);
			$c->addDescendingOrderByColumn(PagePeer::TITLE);
		}
		else
		{
			$c->addAscendingOrderByColumn(PagePeer::DATETIME);
			$c->addAscendingOrderByColumn(PagePeer::TITLE);
		}
		
		$pages = PagePeer::doSelectJoinAll($c);

		$this->proc->setParameter("", "total-item-count", $pageCount);
		$this->proc->setParameter("", "offset", $offset);
		$this->proc->setParameter("", "limit", $limit);
		$this->proc->setParameter("", "desc", $desc);

		$this->proc->setParameter("", "search-result", $request->getAttribute("search-result"));
		if ($request->getAttribute("search-result") != null) $this->resolver->setArgument("search-form", XMLSerializer::serialize($request->getAttribute("search-form")));

		$this->resolver->setArgument("pages", XMLSerializer::serialize($pages));

		$this->template->load(ROOT_DIR."view/views/search/Search.xsl");

		parent::display($request, $response);
	}

}

We get the search string $search and paging parameters such as $offset and $limit from forms. We then tell Propel to look for Pages (which we have defined as our Model class) in the database that match this search string either in their title or their content. First we check the total number of matches ($pageCount), and later retrieve the actual result ($pages) — a sorted array of Pages that should appear on the current search result page.
The rest of the code is just the usual View stuff — setting parameters and passing serialized objects to the XSLT processor, which renders them using an XSLT template into a nice XHTML page of search results when the parent::display($request, $response) is called.

Add a comment

10. Why XSLT is the perfect template engine

2007-06-09 12:20:29 by Martynas Jusevičius

Most of web application architectures these days include one or another kind of a template engine. The template engine applies various templates on data contents and produces various presentation outputs. Using templates, it is easy to achieve style standardization (a common look-and-feel) on the web site, separate concerns of programming and presentation design etc.

We use XSLT 1.0 stylesheets as templates and PHP's XSL extension as a template engine. XSLT is a language for transforming XML documents into other XML documents (not only, really). The engine on which the the transformations are run is usually called an XSLT processor.
For example, using 3 different templates, we produce XHTML, RSS, and Atom presentations from the same data contents.

There is a great variety of template engines, with Smarty being probably the most popular one for PHP. We argue however, that XSLT is the perfect template engine, and that is why we use it in our DIY Framework:

  1. It is a standard
  2. It is non-proprietary and platform-independent
  3. It can be used in a wider context than web templating, i. e. in XML processing in general
  4. It is a functional, Turing-complete language
  5. It is included by default in many platforms
  6. It readily includes many control structures, such as conditional statements/branches, sorting, and even file/HTTP access
  7. There is a great variety of XSLT processors. These are usually separate highly-optimized C or Java libraries and therefore very fast.
  8. Used correctly, it produces only well-formed XML (or XHTML, for that matter)

It is definitely worth learning XSLT instead of a proprietary template language that has yet another kind of syntax and a very narrow application.

Of course, it's easiest to use XSLT when you have your data contents already present in an XML format (e. g. stored in XML files or a native XML database). But even if they are not, it is worth to serialize them into XML and then enjoy all the benefits of XSLT.

Add a comment

Pages: < Previous 1–10 11–20 Next >
Ordering: Ascending Descending