Joomla! 1.5 extensions development hints

0. go through basic Joomla! documentation

Joomla! Beginners guide: [http://docs.joomla.org/Beginners]

Joomla developer network: [http://dev.joomla.org/]
which includes very useful:
Joomla framework API: [http://api.joomla.org/]
Joomla! tutorials on Wiki: [http://dev.joomla.org/component/option,com_jd-wiki/Itemid,32/]

Joomla! forum: [http://forum.joomla.org]

1. project structure

It is useful during development to keep the code in only one place. You can easy use this structure with your
IDEs [http://en.wikipedia.org/wiki/Integrated_development_environment] and VCS [http://en.wikipedia.org/wiki/Version_control_system]

It is recommended to use next structure:

project-root
	com_component
		site
			...
			lang
				...
				en-GB.com_component.ini
				de-DE.com_component.ini
			component.php
		admin
			...
			lang
				...
				en-GB.com_component.ini
				de-DE.com_component.ini
			admin.component.php
			install.sql
			uninstall.sql
		component.xml
	mod_module
		...
		lang
			...
			en-GB.mod_module.ini
			de-DE.mod_module.ini
		module.php
		module.xml
	plg_plugin
		...
		lang
			...
			en-GB.plg_group_plugin.ini
			de-DE.plg_group_plugin.ini
		plugin.php
		plugin.xml
	tpl_temlate
		template.xml
	...

After creation of project structure prepare installation packages with help of Joomla! tutorials and install them to Joomla!.
We will work with local installation (or dedicated server in your LAN) because another variants decries performance of developers.

After extensions installation process change files of extensions installed to Joomla! with GNU/Linux symbolic links [http://en.wikipedia.org/wiki/Symbolic_link] or Windows Vista symbolic links [http://en.wikipedia.org/wiki/NTFS_symbolic_link] of your project files.
Note: Don’t forget to use option “Options +FollowSymLinks” for Apache web-server for directory where your Joomla! installed to use symbolic links.

In Joomla! filenames of extensions has special structure. In mentioned structure names of corresponding extensions in filenames and directories replaced with words component, module, and plug-in.
The word group in files of plugin replaces name of group to which plug-in relate to [content, editors, search, system, user]. Every group defines set of events on which plug-in will be triggered.

Ready to use project has following structure of relations: (<== symbol means symbolic link)

PRJ-ROOT/COM_COMPONENT/SITE <== J_ROOT/COMPONENTS/COM_COMPONET
PRJ-ROOT/COM_COMPONENT/SITE/LANG/en-GB.com_component.ini <== J_ROOT/LANGUAGE/en-GB/en-GB.com_component.ini
PRJ-ROOT/COM_COMPONENT/SITE/LANG/de-DE.com_component.ini <== J_ROOT/LANGUAGE/de-DE/de-DE.com_component.ini

PRJ-ROOT/COM_COMPONENT/ADMIN <== J_ROOT/ADMINISTRATOR/COMPONENTS/COM_COMPONET
PRJ-ROOT/COM_COMPONENT/ADMIN/LANG/en-GB.com_component.ini <== J_ROOT/ADMINISTRATOR/LANGUAGE/en-GB/en-GB.com_component.ini
PRJ-ROOT/COM_COMPONENT/ADMIN/LANG/de-DE.com_component.ini <== J_ROOT/ADMINISTRATOR/LANGUAGE/de-DE/de-DE.com_component.ini

PRJ-ROOT/MOD_MODULE <== J_ROOT/MODULES/MOD_MODULE
PRJ-ROOT/MOD_MODULE/LANG/en-GB.mod_module.ini <== J_ROOT/LANGUAGE/en-GB/en-GB.mod_module.ini
PRJ-ROOT/MOD_MODULE/LANG/de-DE.mod_module.ini <== J_ROOT/LANGUAGE/de-DE/de-DE.mod_module.ini

PRJ-ROOT/PLG_PLUGIN/plugin.php <== J_ROOT/PLUGINS/GROUP/plugin.php
PRJ-ROOT/PLG_PLUGIN/LANG/en-GB.plg_group_plugin.ini <== J_ROOT/ADMINISTRATOR/LANGUAGE/en-GB/en-GB.plg_group_plugin.ini
PRJ-ROOT/PLG_PLUGIN/LANG/de-DE.plg_group_plugin.ini <== J_ROOT/ADMINISTRATOR/LANGUAGE/de-DE/de-DE.plg_group_plugin.ini

As you see languages files of plug-ins installed to administration part of Joomla!. Why so we should ask Joomla! developers.

2. internationalization (i18n)

Most of extensions require internationalization. This mechanism is simple to use in Joomla!, but it has some ambiguous decisions.

To use internationalization support of text messages in the code of extensions instead of output of simple strings we should use next construction: JText::_(’text message’);
This call check current locale and using appropriate localization file returns required string.

For instance if current locale is ‘en-GB’ then it seek for appropriate file:
for “site part” of Joomla!: joomla-root/language/en-GB/en-GB.com_component.ini
and in that file I look for sting with id ‘TEXT MESSAGE’

If it can’t find appropriate file then it returns passed string.

Structure of localization file:
identifier=value

identifier – is a string, it should be written in UPPER CASE.
Value – is a localized value.

Example:
We need to output 2 internationalized strings
echo JText::_(’This is test message.’);
echo JText::_(’Hello world.’);

Then we create localization file for appropriate locale
en-EN.com_component.ini:
THIS IS TEST MESSAGE=This is test message.
HELLO WORLD.=Hello all.

de-DE.com_component.ini:
THIS IS TEST MESSAGE=Das ist testen Meldung.
HELLO WORLD.=Halo eine Welt.

I want to note that in order to use that mechanism for plug-ins you should invoke method loadLanguage of class Jplugin:

loadLanguage(
[name of localization file],
[path to root directory of site part of admin part of Joomla!]

name of localization file, by default plg_group_plugin.ini
path to root directory, can be: “j_root/administrator” or “j_root” (by default)

3. layouts

Layouts is a handy mechanism which let us to avoid using of “if construction” in “view” of the MVC model [http://en.wikipedia.org/wiki/Model-view-controller] which Joomla! 1.5 began to use actively for extensions development.

By default structure of extensions presentation in Joomla (for modules, and components) has next structure:

EXTENSION-ROOT
	VIEWS
	   VIEW
               TMPL
		 default.php
	     view.html.php

Here “view.html.php” file is a common part of presentation which can commonly contains invocations of “model” (MVC) or in other words where we extract data that necessary for data output, and some simple logic. There is a rule to place mature logic to model or controller(MVC).
In the “TMPL” directory we keep different presentations. They contain markup or in other words exact presentation of data.
An file “default.php “ is a default layout, so it will be used if we wasn’t selected another one. You can easily create additional layouts adding them to ‘TMPL’ directory files with name “layoutname.php”.
In order to select specific layout you should in the controller(MVC) before invocation of display() function select its name with command: JRequest::setVar(’layout’, ‘layoutname’);

4. using of AJAX

It is hardy to imagine an application that can be developed nowadays without AJAX. [http://en.wikipedia.org/wiki/Ajax_%28programming%29]

It is much easier to use some javascript library like jquery, mootols, dojo, etc.. to invoke Ajax-based methods.
I like jquery [http://jquery.com]. However Joomla! Developers have selected another Javascript library – mootols [http://mootools.net] and so I earnestly recommend to you to use for ajax methods invocations Mootools library.
If you anyway want to use your favorite JavaScript library you must switch your library to the compatibility mode.
For instance for Jquery it can be do it with:
var jq = jQuery.noConflict();
then instead of ‘$’ you should use ‘jq’ but anyway keep in mind that most of extensions for JavaScript libraries don’t use that mode and so you will have Javascript error because of name collisions.

Example of MVC flow using Ajax invocation:
- Create task in the controller, ex.: getAjaxData

	“controller.php”:
	function getAjaxData() {
		JRequest::setVar('view', 'viewname');
		JRequest::setVar('layout', 'ajaxlayout');

		parent::display();
	}

- Create layout, ex: ajaxlayout

	“viewname/tmpl/ajaxlayout.php”:
	<?php defined('_JEXEC') or die('Restricted access'); 

	global $mainframe;
	echo <ajax data>;	

	$mainframe->close();
	?>

Important note:
You should add invocation: $mainframe->close();
in order to create output flow or it will add Joomla! standard page after result of you Ajax method.
Thus creating concrete layout you can pass any data, don’t forget to setup appropriate header.
For XML [http://en.wikipedia.org/wiki/Xml] it can be: header(”Content-type: text/xml;charset=utf-8″);

On client-side yous should make invoke defined method using Ajax call, using URL like:
JURI::root().’index.php?option=com_component&task=getajaxdata’;

5. mapping of tables to the Database

Joomla! using simple ORM system [http://en.wikipedia.org/wiki/Object-relational_mapping].
In order to use this mechanism you should describe your DB structure with sets of objects that inherit JTable.

For example:
foo.php:

<?php
defined('_JEXEC') or die('Restricted access');

class TableFoo extends JTable {
	var $id = null;
	var $bar = null;

	function TableFoo(& $db) {
		parent::__construct('#__foo', 'id', $db);
	}

	function bind( $from, $ignore=array() ) {
		$from['bar'] = strtoupper($from['bar']);
		return parent::bind($from, $ignore);
	}

	function check() {
		if (empty($this->bar)) {
			$this->setError( ‘Error message’);
			return false;
        		}
		return true;
	}	

	function delete( $oid=null ) {
		$res = parent::delete($oid);

		// here if you need you can define mechanism
		// to delete linked tables
		return $res;
    	}
}
?>

First of all it is necessary to define public variables that corresponding to fields names of table.
Then you should pass name of the table and name of primary key to the constructor.

key methods:

Bind() method using in order to transfer data from external sources (ex.: requst) into object.
Overriding that method you can execute specific data transformations of data before adding to the fields of the object.

Check() method make checking of data in the fields, for example it can check that fields not empty or filled with required range of values, etc.

Delete() method can add specific behavior during deletion of records. For example deleting of linked records.

Also JTable class contains set of other handy methods overriding which you can add appropriate specific behavior.
See Joomla! documentation for details.

possible use:

You can get object in the model (MVC) with following: $row =& $this->getTable(’foo’);

to delete record you invoke: $row->delete($id)

to store record to db:
$row->bind($data);
$row->check();
$row->store();

If then you need get value of primary key you can simply take the value from the object: $row->id;

Surely it is better to add to described calls check of result of methods executions.

CMS-based applications: fast way for creation of web-based solutions

preamble

Nowadays business require full-featured cost-effective solutions with short time to market.
I see only 2 approaches to achieve it:

**development platform which allows rapid visual component-based web-applications development
Unfortunately only .Net platform has it at this moment but we try to avoid proprietary [http://en.wikipedia.org/wiki/Proprietary] solutions.

**lightweight platform which provide already developed full-featured system that can be easily customized with modules - CMS (Content Management System) [http://en.wikipedia.org/wiki/Content_management_system]

I want to make a note here: not every CMS can be used as such base platform.
Appropriate platform should contain well-designed API and documentation for extension development as well as good set of already developed extensions.
There are set of different CMSs, and even commercial ones but we should not use them because we have enough cool open source software.

Selected CMSs

I have reviewed numerous Open-source CMSs for our company to find some noteworthy systems.
Look to this list to understand that we have to select from:
[http://en.wikipedia.org/wiki/Category:Open_source_content_management_systems]

I will not provide you with any comparison due to you can easily find them on the Internet.
There are several platform as base for CMSs: Java, Ruby, Python, PHP

Personally I like Java for strict object-oriented programming methodology, type safety [http://en.wikipedia.org/wiki/Strongly-typed_programming_language], automatic garbage collection, good design of API, and amount of libraries that almost all are open-source.
But: Java based CMSs are heavy, ugly, and still lack functionality.

Most of wonderful (lightweight, pretty, and full-featured) CMSs are written in PHP, and 2 most cool are:

Joomla! [http://en.wikipedia.org/wiki/Joomla%21]
features list: [http://www.joomla.org/content/view/4483/118/]
documentation: [http://docs.joomla.org/]
api: [http://api.joomla.org/]
list of extensions: [http://extensions.joomla.org/]

Typo3 [http://en.wikipedia.org/wiki/TYPO3]
features list: [http://typo3.com/Feature_list.1243.0.html]
documentation: [http://typo3.org/documentation/]
api: [http://typo3.org/fileadmin/typo3api-4.0.0/]
list of extensions: [http://typo3.org/extensions/]

and at the end of the article I will provide to you one of our last solution based on Joomla!:

project name: car auctions site
rough description: site that provide functionality to purchase cars from auctions, forum to discus details, multi language support, vote functionality, customized searches.

platform: Joomla! 1.5
template: free template from [http://joomlashack.com]
Joomla extensions:
forum: simplest forum 1.1.4 [http://extensions.joomla.org/component/option,com_mtree/task,viewlink/link_id,3131/Itemid,35/]
Polls: built-in Joomla! 1.5 vote component
localization support: JoomFish 2.0 [http://www.joomfish.net]

men-hours: 110
site URL: http://www.svidcars.com

As usual I’m waiting for your severe comments and remarks.

simple wordpress sidebar widget step-by-step development

Sidebar and widgets

Sidebar – is an area that take place on the left or on the right from main area. Usually on sidebar placed blog common or quick access elements. This elements called widgets.
Common examples: authors, tags, categories, etc.

In the world of WordPress widget is a plugin subtype. That is activation/deactivation of widgets realized thru the control panel of plug-ins.

Status control of widgets managed in the Design/Widgets panel. There you can add/remove widgets from/to sidebar and change their parameters.

1. How to add new widget

Since widget is plug-in it is behavior like common plug-in in WordPress. In other words it is php-script which placed in directory/subdirectories “/wp-content/plugins”. For correct information representation widget(plug-in) should has header like above:

/*
Plugin Name: Simple Wordpress Sidebar Widget
Plugin URI: http://open.helion-prime.com/Simple-Wordpress-Sidebar-Widget
Description: Simple wordpress sidebar widget.
Version: 1.0
Author: Helion-Prime Solutions Ltd.
Author URI: http://helion-prime.com/
*/

‘Plugin Name’ field described symbolic plug-in name in the system.
‘Plugin URI ‘ contains link to plug-in description.
‘description’ description.
‘version’ version
‘Author’ author name
‘Author URI’ uniform resource identifier

In the upshot in order to add new widget to the system we should:
create file “simple-sidebar-widget.php”
add to file described header
copy file to directory “/wp-content/plugins”

Then in the plug-in control panel we have new plug-in with our name:
‘Simple Wordpress Sidebar Widget’

simple-sidebar-widget.php

<?php
/*
Plugin Name: Simple Sidebar Widget
Plugin URI: http://open.helion-prime.com/Simple-Wordpress-Sidebar-Widget
Description: Simple wordpress sidebar widget.
Version: 1.0
Author: Helion-Prime Solutions Ltd.
Author URI: http://helion-prime.com/
*/
?>

2. Plug-in registration

In the first step we have added simplest plug-in (but not widget yet)
In order to transform it to the widget, we should register it.

Code for sidebar registration:

function simple_sidebar_widget_content_gen($args) {
}

function simple_sidebar_widget_register() {
	if (!function_exists('register_sidebar_widget')) {
			return;
	}

	register_sidebar_widget(__('Simple Sidebar Widget ', 'simple-sidebar-widget'),
		'simple_sidebar_widget_content_gen');
}

add_action('init', 'simple_sidebar_widget_register');

To work widget should contain at least 2 functions:
*initialization (here simple_sidebar_widget_register)
*content generation (here simple_sidebar_widget_content_gen)

To get control in the our code we should create hook on some event. We have 2 events to select from. In our case I have selected ‘init event’ (raised when system loaded and initialized).
Hook created with help of add_action function, as parameter to it passed ‘name of event’ (init) and name of handler function (simple_sidebar_widget_register).

If event raised function simple_sidebar_widget_register receive control and perform following actions:
*check possibility to create widget with help of accessibility of widget registration function – function_exists(’register_sidebar_widget’).
* if required function is accessible it register widget

As you see register_sidebar_widget function receive 2 parameters:
first contain localized name of widget in the widget control panel.
second link to functionality of content-generator (’simple_sidebar_widget_content_gen’).

Now we have full-fledged widget that can be viewed in the widget control panel, it can be added to sidebar (don’t forget to activate it in the plug-in control panel).

3. Representation

If you add our widget to the sidebar it will not show anything. To find any result :) you should add function of content generation in the following way:

function simple_sidebar_widget_content_gen($args) {
	extract($args);

	$title = __('Simple Sidebar Widget ', 'simple-sidebar-widget');
	$widget_content = __('This is simple sidebar widget', 'simple-sidebar-widget');

	echo $before_widget ;
	echo $before_title . $title . $after_title;
	echo '<p>'.$widget_content .'</p>';
	echo $after_widget;
}

First thing that we do is from array of arguments of function that extract variables we create set of variables.

Mainly it is special variables that should be used. Then we create content of widget: in fixed order we output values of special(which contain basic widget markup) and defined variables.

Now we can see our widget on sidebar.

4. Widget setup

If you want to have possibility to setup widget you should change code to the following:

function simple_sidebar_widget_control_gen($widget_content, $show_content) {
?>
<p>
	<label for="widget-content"><?php _e('Content:', 'simple-sidebar-widget'); ?>
		<input class="widefat"
			id="widget-content" name="widget-content"
			type="text" value="<?php echo attribute_escape($widget_content); ?>"
		/>
	</label>
</p>
<p>
	<label for="show-content">
		<input class="checkbox" type="checkbox"
			id="show-content" name="show-content"
			<?php echo $show_content ? 'checked="checked"' : ''; ?>
		/>
		<?php _e('Show content.', 'simple-sidebar-widget'); ?>
	</label>
</p>
<input type="hidden"
	   id="simple-sidebar-widget-submit" name="simple-sidebar-widget-submit"
	   value="1"/>
<?php
}

function simple_sidebar_widget_control() {
	$options = $newoptions = get_option('simple_sidebar_widget');

	if ($_POST['simple-sidebar-widget-submit']) {
			$newoptions['widget-content'] = strip_tags(stripslashes($_POST['widget-content']));
			$newoptions['show-content'] = isset($_POST['show-content']);
	}

	if ($options != $newoptions) {
		$options = $newoptions;
		update_option(’simple_sidebar_widget’, $options);
	}

	simple_sidebar_widget_control_gen(
		$options['widget-content'], $options['show-content']);
}

function simple_sidebar_widget_content_gen($args) {
	extract($args);

	$title = __(’Simple Sidebar Widget ‘, ’simple-sidebar-widget’);

	$options = get_option(’simple_sidebar_widget’);
	$show_content = $options['show-content'] ? true : false;
	$widget_content =empty($options['widget-content']) ?
		__(’This is simple sidebar widget’, ’simple-sidebar-widget’) :
		$options['widget-content'];

	echo $before_widget ;
	echo $before_title . $title . $after_title;
	if ($show_content) {
		echo ‘<p>’.$widget_content .’</p>’;
	}
	echo $after_widget;
}

function simple_sidebar_widget_register() {
	if (!function_exists(’register_sidebar_widget’)) {
			return;
	}

	register_sidebar_widget(__(’Simple Sidebar Widget ‘, ’simple-sidebar-widget’),
		’simple_sidebar_widget_content_gen’);
	register_widget_control(__(’Simple Sidebar Widget ‘, ’simple-sidebar-widget’),
		’simple_sidebar_widget_control’);
}

What changed in our code:

In function ’simple_sidebar_widget_register’ one invocation added (’register_widget_control’), it register function which catch widget configuration change event (’simple_sidebar_widget_control’).

In the generator of widget content additional code added that receives current configuration of widget get_option(’simple_sidebar_widget’).
Here parameter ’simple_sidebar_widget’ is identifier of parameters set that used in our widget.
Then into variables $show_content and $widget_content extracted current values of parameters.

As I already noted for event processing of configuration changes we should add appropriate event-handler function (’simple_sidebar_widget_control’). In this function we extract parameters from request and analyze changes, also this function create content of configuration form (this functionality moved to ’simple_sidebar_widget_control_gen’).

After we added above code in the parameters of widget we have 2 fields.
One field contains content that should be outputted.
Second field is a switch which allow/forbid output of content.

In closing I want to note that widgets work only with themes that support sidebar.
Described methodology work for WordPress >=2.5, although it is almost the same for previous versions.

related links:
plug-in development - http://codex.wordpress.org/Writing_a_Plugin
list of actions - http://codex.wordpress.org/Plugin_API/Action_Reference
localization: http://codex.wordpress.org/Translating_WordPress

relevance calculation and popularity

preamble

In this post I try to understand why some search engines more popular, how we can test relevance, and how popularity of search-engines related with relevance.

1 approach: we should test them on relevance

Here we just want to enter request and see who can provide better results.

You can think that I will generate some requests by some rules and then I will say to you who is best. We have many works like that.

But I say to you: relevance is a relative conception that has statistical constituent.
How to understand it simple:
Think about requests like “python” or “ruby”.
We get the response from search-engine which give us real good results with information about “python” or “ruby” but classify them as computer languages.
If we are software-engineers we think search-engine works good, if we are biologist we think differently:)

We can provide search engine with additional information using advanced knowledge about our request to get more relevant result. From another side sometimes we want to find information we don’t understand deeply at current moment, so we don’t know how define it and how then check whether we got optimal result.
Therefore we will not judge search-engine by so relative conception like relevance.

I have an opinion that we should classify information according to at least basic sections.

There are several problems:

If we provide many branches we will make situation where hard to describe our request with most appropriate appropriate category. We have such situation in web directories[http://en.wikipedia.org/wiki/Web_directory]. It is important to find balance between relevance and difficulty to describe of request.

Who should divide information which already crawled into categories. Algorithms help us to find and assign correct weight to pages (see my article: “Relevance and cheat techniques” for details about current techniques which search-engines use to search and estimate. We can develop another algorithms but it seems that at current moment it is better to use people. It can be volunteers which Jimmy Wales, creator of Wikipedia[http://en.wikipedia.org/wiki/Wikipedia] want to use for open-source[http://en.wikipedia.org/wiki/Open-source] search-engine he is working on.

Or we can give possibility to mark information with appropriate category to everyone.We have another problem how to believe to everyone. People like to cheat.

Possible answers are: statistical faith (10 say cool, 2 say bad; result: quite cool), community of trusted people, used to solve computer security problems (simplistically: if someone truthful think I am truthful and I trust to my friend; result: we can believe to my friend), or combinations.

Check some of the following to see how it can work by this time
StumbleUpon [http://en.wikipedia.org/wiki/Stumbleupon]
Technorati [http://en.wikipedia.org/wiki/Technorati.com]
Digg [http://en.wikipedia.org/wiki/Digg]

2 approach: search engine database does matter

Here we want just want to compare search engines databases and make decisions.

We know who stroked first. It was Google in 2000 year they said: “Searching 8,xxx,xxx,xxx web pages”. It is simply advertisement we know it. But others have strained..

Index size number estimation it is like a game. Which rules we should use? Or in other words how to calculate?
We will not worry about it..

On 8/05/2005 Tim Mayer on Yahoo! Search blog claimed that the “[Yahoo!] index now provides access to over 20 billion items” which include “19.2 billion web documents, 1.6 billion images, and over 50 million audio and video files”. [http://www.ysearchblog.com/archives/000172.html]

Google stopped providing quantity of pages indexed, which was listed as 8 billion, “because people don’t necessarily agree on how to count it,” Dr. Eric Schmidt Chairman of the Board and CEO. [http://news.zdnet.co.uk/internet/0,1000000097,39222233,00.htm?r=1]

In 2 days after Yahoo post on University of California at Berkeley blog visiting Professor John Battelle said that Google refuted this “.. scientists are not seeing the increase claimed in the Yahoo! index”. [http://battellemedia.com/archives/001790.php]

Then we had independent research about this [http://vburton.ncsa.uiuc.edu/indexsize.html] then some critics like: [http://aixtal.blogspot.com/2005/08/yahoo-missing-pages-3.html]

Then some corrections but still Yahoo and Google search engines truncate results returned to the user after 1,000 results so it is hard to be sure.

So we don’t have good approach to compare databases sizes. Search-engines companies seems not interesting in creating of common rules of playing (common rules of database index calculation)

instead of conclusion:
It is hard to compare because we should preciously define our criterions and notions.

If so how we can know who is better?
We can’t. There are some additional points like religion: “I like Google” or passion for design: ”MS Search looks better”, etc..

search engines relevance and cheat techniques

preamble

All of us fill that relevance [http://en.wikipedia.org/w/index.php?title=Relevance_%28Computer_Science)] of documents that we search thru search engines become worse.
This happened because of increasing size and dynamic nature of internet which hard to analyze and monitor even for web-crawlers [http://en.wikipedia.org/wiki/Web_crawler], and cheaters which invent more advanced methods of cheating.

relevance – sum of factors

Common factors I consider as important for site ranking:

patented PageRank algorithm [http://en.wikipedia.org/wiki/PageRank]
Which creators of Google Larry Page and Sergey Brin developed as part of a research project about a new kind of search engine in about 1995 or his numerous modifications.

Personalized search [http://www.google.com/history]

“It helps deliver more personalized search results based on what you’ve searched for on Google and which sites you’ve visited.”
Google Web history

Google try to find some dependency between search requests of users. It sound like good enhancement based on if I am looking for java or C++ I can be programmer and so I can prefer related resources. But occasionally I may want to find a game or a film and this can make result worse for this particular search, but in general case it should work fine. Or even better we can make additional research if this particular request related with things I searched before and if not we can have general case for searching.

direct weight analyze
[keyword density, anchor text, formatting elements analyze: font size, formatting tags: <title>,<b>,<h1>,<em>]
Search engine can analyze frequency of keyword on related page, emphasis of notes, placement relatively to begin of page, text under anchor, precision of requested phrase. Whether information reproduced from another sources, in which time information became available.

domain name analyze (educational, nonprofit, commercial, government, etc.)
Search engine can analyze which domain name can be more appropriate for request
If you looking for “government rules” it can give more weight to government (.org) first level domain sites.
If you looking for something in Russian it can be good idea to give more weight to Russian first level domain name sites (.ru)

site size analyze
Search engine can give higher mark to bigger site by compare of number of pages related to same domain name

intelligent site state analyze
Site updating: site last update, percent of updating;
Site maintains quality: broken links, number of type mistakes;

morphology analyze (intelligent ignoring of stop words, slang, obscene language)
sure we should ignore words like: very, of, occasionally, and…; but compare
beauty of car – we want to find what is the beauty when we are say about cars
beauty and car – we want to find how beauty of something or someone can be related to cars
or
paper box – box made of paper
paper and box – maybe shop where we can boy papers, boxes…

Morphology analyze can provide for us additional forms of requested entity for additional searches.
We can find more technical resources that contain special slang, and descries weight of site with obscene language if user didn’t provide request with such language.

using of social networks [http://en.wikipedia.org/wiki/Social_network]
Modern approach. After using of sets of different algorithms we use people to make estimation of resources. Real and working example is a StumbleUpon with current community size about 3,095,859 [http://en.wikipedia.org/wiki/StumbleUpon].

StumbleUpon chooses which new webpage to display based on the user’s ratings of previous pages, ratings by his/her friends, and by the ratings of users with similar interests
StumbleUpon site

“Next time you want to wander the Web, forget about Googling it. Stumble it.”
Wall Street Journal

If it is so cool why Google don’t provide is as part of their search. I think it is because of StumbleUpon patent-pending [http://en.wikipedia.org/wiki/Patent_pending] toolbar system. Search engine companies should invent something at least slightly different to overcome patent issues or bay it. By the way eBay [http://en.wikipedia.org/wiki/Cloaking]
According to GOOGLE webmaster FAQ cloaking is

The term “cloaking” is used to describe a website that returns altered webpages to search engines crawling the site. In other words, the webserver is programmed to return different content to Google than it returns to regular users, usually in an attempt to distort search engine rankings. This can mislead users about what they’ll find when they click on a search result. To preserve the accuracy and quality of our search results, Google may permanently ban from our index any sites or site authors that engage in cloaking to distort their search rankings.

basic idea: to give to web-crawler specially prepared page content with good keywords.
popularity: not very popular tactic. Not easy to implement it in a good way.

tactic: cheater should make special pages with keywords smeared by the pages, it is very important not go too far. Cheater should find special balance of common word, key words, not related words, etc.. Then he should give those pages to web-crawler when it comes to crawl pages. People recognize crawler by user-agent greetings (HTTP_USER-AGENT) [http://en.wikipedia.org/wiki/User_agent] like: “Googlebot/2.1” or using special database with IP-range that search company has or HTTP referrer [http://en.wikipedia.org/wiki/Referrer] or using some combinations.

When web-crawler crawl pages it cache them so cheaters should find a way to avoid it using things like search engines specific metategs like: or general metatags like:
but “pragma” doesn’t work in IE 5 so in order to assure a non-cache, you’ll need to add another meta tag:
and so on ..

Additionally cheaters can rotate different contents to make visibility of fast site modifications (news channel..)
or provide different content for different web-crawlers using robots.txt file [http://en.wikipedia.org/wiki/Robots.txt]:
User-Agent: Googlebot/2.1
Disallow: /doorway/lycos/
User-Agent: YahooBot
Disallow: /doorway/lycos/

As you see it is not so easy to be cheater. It is not talking about special schemes that search companies use to catch cheaters like:
incorrect user-agent names or special IPs for content checking.
Today we have off the shelf cloaking programs. Sure it is bad idea to use it, it can be trojan, virus, etc.. and you never get optimal solution as I wrote above.

There are many disputes about page cloaking: it is popular today to provide special content for mobile devices, vary content using geographical parameters, or make personalization for users. Is it page cloaking? I think personalized content delivery is not page cloaking. But search engines engineers know better. Ask google ..:)

Multiply entry point (doorway)
Cheaters buy different domain names that contain different keywords which can be targeted to the same site, or they can make several sites with slightly altered content which lead to some more important site.

basic idea: to have multiply entry point to one site
popularity: quite popular tactic.

Old techniques
There are many old techniques like:
invisible text: examples: black keywords on black background, very small font;
hidden frames, duplicate pages, keywords in title, keywords in comments, keywords in style tags, keywords in hidden values ..
I have not written about them simply because I think it is passed stage of search engines evolution.

PS: Sure I have missed something new and fantastic.
If you know about these techniques mail me and I will add it with big pleasure.

related links:
Early google architecture according to Sergey Brin and Lawrence Page work at Stanford University [http://infolab.stanford.edu/~backrub/google.html]
Google guide for webmaster [http://www.google.com/intl/az/webmasters/guidelines.html]
Google reporting page about cheaters [http://www.google.com/contact/spamreport.html]
Google sitemaps (Statistics, diagnostics and management of Google’s crawling) [http://www.google.com/webmasters/sitemaps/]
Keyword density [http://en.wikipedia.org/wiki/Keyword_density]
Google bomb technic: [http://en.wikipedia.org/wiki/Google_bomb]