Drupal development: Vlastní políčka v typech obsahu #1

Vydáno:

Jiří Kupka

Tento článek pojednává o vytvoření "statického políčka", tj. políčka, které je přiřazeno automaticky k typu obsahu programově (Title, URL path settings, ...) a není možné ho přidat ve smyslu "vlastní políčko určitého datového typu" (Obrázky, Soubory, DateField, ...). O definování vlastního typu pole bude pojednávat připravovaný článek Vlastní políčka v typech obsahu #2.

Občas potřebujeme přidat do výpisu node nějaké políčko. Chceme ho přidávat automaticky ke všem typům obsahu bez toho, aniž by ho musel administrátor ručně přidávat nebo mohl smazat. Takovým políčkem může být například jednoduché počítadlo návštěv (pro jednoduchost příkladu). Budeme chtít, aby se v detailu node vypisovaly statistiky a jako bonus dovolíme správci webu jeho nastavení - například v jakém formátu se statistiky mají zobrazit.

Začneme trošku ze široka od toho, jak udělat funkční řešení až k tomu, jak toto řešení postupně vylepšovat. Proto začneme u hooku hook_node_view. Tento hook se volá vždy, když je zavolána funkce node_view(). To znamená zaručeně například při zobrazení node v detailu na stránce /node/XXX. V tomto hooku si programově přidáme nějaké políčko - resp. generovaný text, který chceme v detailu naší stránky zobrazit.

/**
 * Implements hook_node_view().
 */
function my_module_node_view($node, $view_mode, $langcode) {
	$node->content['my_field_name']['#markup'] = t("Visits: !visits",array('!visits' => my_module_get_visits($node)));
}

A to vlastně stačí. S funkcí si můžeme vyhrát a výstup políčka určovat například dle typu obsahu $node->type či jiných vlastností, které získáváme v argumentech funkce. Jedná se o nejjednodušší přístup. Místo klíče #markup můžeme využít renderování pomocí theme funkce (#theme) a další. Doporučuji nahlédnout do dokumentace k funkci hook_node_view.

V tomto okamžiku záleží z velké části na tom, jakou podobu má soubor node.tpl.php, resp. jakým způsobem se obsah node vypisuje uživateli. Obsah našeho políčka by měl být v tomto okamžiku v šabloně k nalezení pod proměnnou $content['my_field_name']. V původním node.tpl.php se všechny políčka renderují pomocí render($content), což nám zajistí, že se budou uplatňovat vlastnosti a hlavně pořadí polí definované ve správě zobrazení. Pokud tento přístup nepoužíváme a tiskneme políčka přímo z $node->field či každé zvlášť přes render($content['field_xxx']), budeme si muset i naše políčko vytisknout do šablony zvlášť - print render($content['my_field_name']). Jak jsem již výše psal, pokud tiskneme celý obsah proměnné $content, bude nám akceptovat pořadí definované ve správě zobrazení - tudíž chceme, ať se nám naše políčko zobrazuje i v tomto seznamu a správce má možnost jej přesunout, kam potřebuje. K tomu využijeme funkci hook_field_extra_fields.

/**
 * Implements hook_field_extra_fields().
 */
function my_module_field_extra_fields() {
	$extras = array();
	$content_types = node_type_get_types();
 
	foreach($content_types as $ct) {
		$extras['node'][$ct->type] = array(
			'display' => array(
				'my_field_name' => array(
					'label' => t("Statistics"),
					'description' => t("Simple statistics"),
					'weight' => 10,
				),
			),
		);	
	}
 
	return $extras;
}

Výše vypsaný kód je více-méně jasný - máme pole $extras, kde prvním klíčem je bundle, tj. v našem případě node. Druhým klíčem je entity_type - my chceme políčko pro všechny typy obsahu, takže definujeme pro všechny typy obsahu. Třetí úrovní je klíč display, ve kterém definujeme políčko právě pro správu zobrazení. Další klíče jsou jasné - název, popis, výchozí váha.

V tomto okamžiku máme prakticky hotové políčko, které je možné spravovat a nastavit mu zobrazení přes administraci. Zde bychom přestali, kdyby políčko nepotřebovalo nějaké dodatečné nastavení. My chceme umožnit správci při vytváření node toto políčko ještě nastavit. V příkladu si v editaci node budeme definovat, jak se pole zobrazí na konkrétní stránce - pouze počet návštěvníku stránky nebo i poslední přístup.

/**
 * Implements hook_field_extra_fields().
 */
function my_module_field_extra_fields() {
	$extras = array();
	$content_types = node_type_get_types();
 
	foreach($content_types as $ct) {
		$extras['node'][$ct->type] = array(
			// display part
			// ...
			'form' => array(
				'my_field_name' => array(
					'label' => t("Statistics"),
					'weight' => 10,
				),
			),
		);	
	}
 
	return $extras;
}

Ke klíči display z předchozí sekce se přidal klíč form. Díky tomuto klíči se nám zobrazí políčko i ve správě polí a opět jsme tím dostali možnost určit si, kde se pole bude zobrazovat na editační stránce nodu - tj. měnit mu tak jednoduše váhu. Kromě toho musíme toto pole přidat do editačního formuláře - to uděláme jednoduše klasicky přes hook_form_alter. Důležité je využívat jako klíč pořád ten stejný název - v našem případe my_field_name.

/**
 * Implements hook_form_alter().
 */
function my_module_form_alter(&$form, &$form_state, $form_id) {
	if(strpos($form_id,'_node_form')) {
 
		$form['my_field_name'] = array(
			'#type' => 'select',
			'#title' => t("Statistics output method:"),
			'#options' => array(
				'count_only' => t("Count only"),
				'last_access' => t("Count and last access"),
			),
		);
		// ...

Nastavenou hodnotu si můžeme ukládat do systémové proměnné variable_set/get nebo do námi vytvořené vazební tabulky nid <-> display_type a pak ji načítat na základě nid ve funkci my_module_node_view a podle toho zobrazit správný výstup pole.