Drupal development: Context, podmínky

Vydáno:

Jiří Kupka

Modul Context je jeden z modulů, které při běžné tvorbě jednoduchých webů nemusíte používat nebo vůbec znát. Na druhou stranu, když se jej naučíte ovládat a zjistíte, kdy a na co ho použít, je to neuvěřitelný pomocník.
Context vlastně vytváří prostředí, kdy na základě určité podmínky (kontextu/stavu webu) dojde k nějaké reakci, která pozmění výslednou, vyrenderovanou stránku. Možná si Context v této chvíli budete trochu plést s modulem Rules, což je celkem pochopitelné. Rules oproti Contextu na základě nějaké podmínky vykoná nějakou akci s daty, okolním prostředím apod. Kdybych to měl hodně zjednodušit a přirovnat to k nejznámějšímu návrhovému vzoru - MVC, řekl bych, že Context si pohrává s view, Rules s modelem.

U jednoho projektu jsme měli zařazeny články do kategorií. Podle toho, v jaké kategorii se článek nacházel, tak se upravilo prostředí webu - načetly se přidané css, změnilo se zobrazení bloků apod. Tento případ teď vezmu trochu zjednodušeně a pokusím se sepsat postup, jak vytvořit pro Context podmínku "Pokud je článek v kategorii, přidej css".

Vytvoříme si jednoduchý modul jménem taxonomy_css. Do taxonomy_css.module vložíme následující kód:

<?php
/**
* Implements hook_context_registry().
*/
function taxonomy_css_context_registry() {
	return array(
		'conditions' => array(
			'taxonomy_css' => array(			// Jméno podmínky může být jakékoliv. Nemusí být shodné s modulem
				'title' => t('Taxonomy css'), 
				'plugin' => 'taxonomy_css_context_condition',
			),
		),
	);
}

Ve funkci hook_context_registry() si registrujeme buď podmínky - conditions, nebo reakce - reactions. Z funkce potom vracíme jejich pole. V našem případě si chceme zaregistrovat podmínku se jménem taxonomy_css. Jméno podmínky nemusí být shodné s názvem modulu. Jelikož podmínek a reakcí může být víc, nedával by opak ani smysl. taxonomy_css je opět pole, které vrací svůj název čitelný člověkem a plugin, což je identifikátor pluginu, který nám bude podmínku obsluhovat.
Do taxonomy_css.module si dále přidáme:

/**
* Implements hook_context_plugins().
*/
function taxonomy_css_context_plugins() {
	$plugins = array();
	$plugins['taxonomy_css_context_condition'] = array(
		'handler' => array(
			'path' => drupal_get_path('module', 'taxonomy_css') . '/plugins', 
			'file' => 'taxonomy_css_condition.context.inc', 
			'class' => 'taxonomy_css_context_condition', 
			'parent' => 'context_condition',
		),
	);
	return $plugins;
}

Ve funkci hook_context_plugins() už vracíme seznam pluginů a základní informace o nich. Vrací se opět asociativní pole, kde hlavním klíčem je identifikátor pluginu, který jsme zaregistrovali v hook_context_registry(). Klíč path říká, ve kterém adresáři nalezneme soubor z klíče file. class říká, která třída bude plugin zastupovat, která ho obslouží.
V adresáři s modulem si vytvoříme soubor plugins/taxonomy_css_condition.context.inc a do něj vložíme

<?php
class taxonomy_css_context_condition extends context_condition {
	function condition_values() {
		$terms = taxonomy_get_tree(TERM_TID);
		$output = array();
 
		foreach($terms as $term) {
			$output[$term->tid] = $term->name;
		}
 
		return $output;
	}
 
	function execute() {
		foreach($this->get_contexts() as $context) {
			if(isset($context->conditions['taxonomy_css']['values'])) {
				$selected_tid = reset($context->conditions['taxonomy_css']['values']);
				if(taxonomy_css_is_page_in_term($selected_tid)) {
					$this->condition_met($context);
				}
			}
		}
	}
 
}

Takto vypadá třída taxonomy_css_context_condition. Dědí z context_condition, což je bázová třída pro context. Doporučuji se mrknout do adresáře plugins/ - může se vám někdy občas hodit dědit z nějaké jiné třídy. V metodě condition_values() vypisujeme seznam možností, pomocí kterých je možné podmínku nějakým způsobem upravit - tady vypisuji seznam termínů, z kterých si může uživatel vybrat. Potom tady je metoda execute(), která se spouští tam, kde řekneme (níže). Cyklem projdeme všechny vytvořené kontext filtry, které v sobě mají naši podmínku. Potom si získáme uživatelem vybraný term a kontrolujeme, zda stránka tento termín obsahuje (řekněme, že jsme si napsali funkci taxonomy_css_is_page_in_term(), která nám to poví). Pokud podmínka kontextu souhlasí, zavoláme metodu condition_met(), čímž řekneme, že byla podmínka splněna v daném kontextu.

Nyní je ještě důležité říct, kdy se má podmínka kontrolovat. Někdy to je vhodné vždy, někdy, když se renderuje stránka, nebo vykreslují bloky. My to budeme chtít vždy, proto si ještě v našem malém modulu vložíme hook_init() a vložíme následující kód.

function taxonomy_css_init() {
	if($plugin = context_get_plugin('condition', 'taxonomy_css')) {
		$plugin->execute();
	}
}

Tímto si získáme náš plugin a spustíme metodu execute().