Outils pour utilisateurs

Outils du site


Panneau latéral

devguide:createmodule:createblocklist

Création d'un bloc de liste

Il est maintenant possible de créer des recettes dans notre module et de les visualiser en backoffice, mais tout ceci ne sert à rien s'il l'on n'affiche rien en front office. Nous allons donc remédier à cela en créant un premier bloc qui a pour but de lister les différentes recettes que l'on a saisi.

Nous générons les fichiers du bloc à l'aide de la commande add-document-block :

php framework/bin/change.php add-document-block -h
Add-document-block: initialize a block for some specific work
Usage: change.php add-document-block <moduleName> <documentName> <blockType> [icon].
Where <blockType> in:
- detail
- list

Ajout du bloc

Ajoutons notre bloc de liste des recettes :

php framework/bin/change.php add-block recipes Recipelist
== Add block ==
Generating <path>/modules/recipes/lib/blocks/BlockRecipelistAction.class.php
Generating <path>/modules/recipes/templates/Recipes-Block-Recipelist-Success.all.all.html
Add modules_recipes_Recipelist in <path>/modules/recipes/config/blocks.xml.
== Compile locales ==
recipes module locales compiled
== Clear webapp cache ==
Webapp cache directory cleared

== Clear template cache ==
Template cache directory cleared

Locales successfully compiled

=> Block 'Recipelist' added in module 'recipes'.
Please now edit <path>/modules/recipes/lib/blocks/BlockRecipelistAction.class.php.

Paramétrer le bloc

Nous allons ajouter un paramètre au bloc afin de contrôler le nombre de recette que l'on va afficher par page. Nous éditons donc le fichier config/blocks.xml et on ajoute une section parameters, on va également indiquer une valeur minimale (1), une valeur maximale (100) et une valeur par défaut (10) :

<?xml version="1.0" encoding="utf-8"?>
<blocks>
    <block type="modules_recipes_Recipelist" icon="">
        <parameters>
            <parameter name="nbRecipesPerPage" type="Integer" default-value="10">
                <constraints>min:1;max:100</constraints>
            </parameter>
        </parameters>
    </block>
</blocks>

Permettre de retrouver le bloc dans le site

Il peut être pratique de pouvoir retrouver la page contenant le bloc de liste des recettes ; par exemple pour présenter un lien dans la fiche de détail d'une recette permettant de revenir à la liste des recettes. Pour ce faire nous crééons un “tag” pour le bloc, en créant le fichier recipes/config/modules_website.page.tags.xml et en y déclarant le tag contextuel pour le bloc de liste :

<?xml version="1.0" encoding="utf-8"?>
<tags>
  <tag labeli18n="m.recipes.bo.blocks.recipelist.title" icon="list-block">contextual_website_website_modules_recipes-list</tag>
</tags>

Pour que le tag soit pris en compte, il suffit d'utiliser la commande compile-tags :

php framework/bin/change.php compile-tags
== Compile tags ==
== Clear webapp cache ==
Webapp cache directory cleared

=> Tags compiled successfully

Action du bloc et template

A ce stade nous avons un bloc de liste opérationnel sans avoir écrit une ligne de code, juste en ayant utilisé l'assistant disponible en ligne de commande. Nous allons modifier un peu le code généré pour avoir un rendu un peu plus attrayant.

Dans le code PHP on va :

  • modifier la classe du service du document recipe pour ajouter une méthode qui retourne le nombre de recettes et une autre qui retourne un set de recettes
  • changer la vue à utiliser par le bloc lorsqu'il s'affiche en back office

Code du service

Cliquez ici pour voir le fichier recipes/lib/services/RecipeService.class.php

Cliquez ici pour voir le fichier recipes/lib/services/RecipeService.class.php

Cliquez ici pour voir le fichier recipes/lib/services/RecipeService.class.php

	/**
	 * Return how many recipes we at all
	 * @param Boolean $onlyPublished
	 * @return Integer
	 */
	public function getRecipesCount($onlyPublished=true)
	{
		$query = $this->pp->createQuery('modules_recipes/recipe', false);
		$query->add(Restrictions::published());
		$query->setProjection(Projections::rowCount());
		$recipesCount = $query->find();
		return $recipesCount[0]["rowcount"];
	}
	
	/**
	 * Get a set of recipes
	 * @param Integer $offset
	 * @param Integer $length
	 * @param String $orderOn
	 * @param String $orderDir either 'asc' or 'desc'
	 * @param Boolean $onlyPublished
	 * 
	 * @return recipes_persistentdocument_recipe[]
	 */
	public function getRecipesSet($offset=0, $length=10, $orderOn='label', $orderDir='asc', $onlyPublished=true)
	{
		$query = $this->createQuery();
		$order = Order::byString($orderOn, $orderDir);
			
		$query->setFirstResult($offset*$length)->setMaxResults($length)->addOrder($order);
		$query->add(Restrictions::published());
		return $query->find();
	}



Code du bloc

Cliquez ici pour voir le fichier recipes/lib/blocks/BlockRecipelistAction.class.php

Cliquez ici pour voir le fichier recipes/lib/blocks/BlockRecipelistAction.class.php

Cliquez ici pour voir le fichier recipes/lib/blocks/BlockRecipelistAction.class.php

<?php
/**
 * recipes_BlockRecipelistAction
 * @package modules.recipes.lib.blocks
 * @method recipes_BlockRecipelistConfiguration getConfiguration()
 */
class recipes_BlockRecipelistAction extends website_BlockAction
{
	/**
	 * @see website_BlockAction::execute()
	 *
	 * @param f_mvc_Request $request
	 * @param f_mvc_Response $response
	 * @return String
	 */
	public function execute($request, $response)
	{
		if ($this->isInBackoffice())
		{
			return website_BlockView::NONE;
		}
			
		// Get params
		$nbItem = $this->getConfiguration()->getNbRecipesPerPage();
		$orderProperty = $request->getParameter('orderBy', 'label');
		$orderDirection = $request->getParameter('orderByDirection', 'asc');
		$page = 1;
		if ($request->hasParameter('page'))
		{
			$page = $request->getParameter('page');
		}
		
		// Count how many recipes we have at all
		$rsi = recipes_RecipeService::getInstance();
		$recipesCount = $rsi->getRecipesCount();
		
		if ($recipesCount > 0)
		{
			// Get published recipes.
			$recipes = $rsi->getRecipesSet($page-1, $nbItem, $orderProperty, $orderDirection);
		
			// recipes pagination.
			$paginator = new paginator_Paginator('recipes', $page, $recipes, $nbItem, $recipesCount);
			$request->setAttribute('recipes', $paginator);
		}
		
		// Set attributes in request
		$request->setAttribute('nbItem', $nbItem);
		$request->setAttribute('page', $page);
		$request->setAttribute('orderBy', $orderProperty);
		$request->setAttribute('orderByDirection', $orderDirection);
		
		// Add link rel canonical.
		$this->getContext()->addCanonicalParam('page', $page > 1 ? $page : null, $this->getModuleName());
        
		return website_BlockView::SUCCESS;
	}
}


Nous avons modifié le code de la classe finale de notre document recipes/persistendocument/recipe.class.php pour :

  • indiquer les données que nous allons indexer pour le moteur de recherche
  • y ajouter 3 méthodes utilisées par le template

Cliquez ici pour voir le fichier recipes/persistendocument/recipe.class.php

Cliquez ici pour voir le fichier recipes/persistendocument/recipe.class.php

Cliquez ici pour voir le fichier recipes/persistendocument/recipe.class.php

<?php
/**
 * Class where to put your custom methods for document recipes_persistentdocument_recipe
 * @package modules.recipes.persistentdocument
 */
class recipes_persistentdocument_recipe extends recipes_persistentdocument_recipebase implements indexer_IndexableDocument
{
	/**
	 * Get the indexable document
	 *
	 * @return indexer_IndexedDocument
	 */
	public function getIndexedDocument()
	{
		$indexedDoc = new indexer_IndexedDocument();
		// TODO : set the different properties you want in you indexedDocument :
		// - please verify that id, documentModel, label and lang are correct according your requirements
		// - please set text value.
		$indexedDoc->setId($this->getId());
		$indexedDoc->setDocumentModel('modules_recipes/recipe');
		$indexedDoc->setLabel($this->getLabel());
		$indexedDoc->setLang($this->getLang());
		$indexedDoc->setText($this->getIngredients()." ".$this->getPreparation());
		return $indexedDoc;
	}

	/**
	 * Method called by the list template in order to display or not the first recipe column
	 * @return boolean
	 */
	public function hasBasicInfo()
	{
		if (f_util_ObjectUtils::isEmpty($this->getPeopleNumber())
				&& f_util_ObjectUtils::isEmpty($this->getPreparationTime())
				&& f_util_ObjectUtils::isEmpty($this->getCookingTime())
				&& f_util_ObjectUtils::isEmpty($this->getRestTime()))
		{
			return false;
		}
		return true;
	}
	
	/**
	 * Method called by the list template in order to display or not the second recipe column
	 * @return boolean
	 */
	public function hasDifficultyAndCost()
	{
		if (f_util_ObjectUtils::isEmpty($this->getDifficulty())
				&& f_util_ObjectUtils::isEmpty($this->getCost()))
		{
			return false;
		}
		return true;
	}
}


Nous avons également créé quelques fichiers de locales pour le template.

Cliquez ici pour voir le code final du template recipes/templates/Recipes-Block-Recipelist-Success.all.all.html

Cliquez ici pour voir le code final du template recipes/templates/Recipes-Block-Recipelist-Success.all.all.html

Cliquez ici pour voir le code final du template recipes/templates/Recipes-Block-Recipelist-Success.all.all.html

<h2 change:h="">${trans: m.recipes.fo.recipes-list-title,ucf}</h2>

<dl class="inline-list">
    <dt>${trans: m.recipes.fo.order-by, ucf}</dt>
    <dd>
	    <a tal:condition="php: orderBy != 'label'"
	        change:currentPageLink="recipesParam[orderBy] 'label'; recipesParam[page] '1'">
	        ${trans: m.recipes.fo.recipe-name, ucf}</a>
	    <span tal:condition="php: orderBy == 'label'">${trans: m.recipes.fo.recipe-name, ucf}</span>
	    <span class="separator"> | </span>
    </dd>
    <dd>
	    <a tal:condition="php: orderBy != 'difficulty'"
	        change:currentPageLink="recipesParam[orderBy] 'difficulty'; recipesParam[page] '1'" >
	        ${trans: m.recipes.document.recipe.difficulty, ucf}</a>
	    <span tal:condition="php: orderBy == 'difficulty'">${trans: m.recipes.document.recipe.difficulty, ucf}</span>
	    <span class="separator"> | </span>
    </dd>
    <dd>
	    <a tal:condition="php: orderBy != 'document_creationdate'"
	        change:currentPageLink="recipesParam[orderBy] 'document_creationdate'; recipesParam[page] '1'">
	        ${trans: m.recipes.fo.recipe-add-date, ucf}</a>
	    <span tal:condition="php: orderBy == 'document_creationdate'">${trans: m.recipes.fo.recipe-add-date, ucf}</span>
    </dd>
</dl>
<dl class="inline-list">
    <dt>${trans: m.recipes.fo.order-by-direction, ucf}</dt>
    <dd>
	    <a tal:condition="php: orderByDirection != 'asc'"
	        change:currentPageLink="recipesParam[orderByDirection] 'asc'; recipesParam[page] '1'">
	        ${trans: m.recipes.fo.order-by-asc,ucf}</a>
	    <span tal:condition="php: orderByDirection == 'asc'">${trans: m.recipes.fo.order-by-asc, ucf}</span>
	    <span class="separator"> | </span>
	</dd>
    <dd>
	    <a tal:condition="php: orderByDirection != 'desc'"
	        change:currentPageLink="recipesParam[orderByDirection] 'desc';recipesParam[page] '1'">
	        ${trans: m.recipes.fo.order-by-desc, ucf}</a>
	    <span tal:condition="php: orderByDirection == 'desc'">${trans: m.recipes.fo.order-by-desc, ucf}</span>
	</dd>
</dl>

<div change:paginator="recipes"></div>
<ol class="document-list">
	<tal:block tal:repeat="recipe recipes">
		<li class="${php: repeat.recipe.odd ? 'odd' : 'even'}">
			<h3 change:h="">
                <img tal:condition="recipe/getVegetarian" change:img="front/vegetarian.png" change:i18nattr="title m.recipes.fo.vegetarian; alt m.recipes.fo.vegetarian;"/>
                ${recipe/getLabelAsHtml}
            </h3>
			<div>
				<tal:block tal:condition="recipe/getPicture" >
					<img change:media="document recipe/getPicture; class 'document-visual'; format 'modules.media.frontoffice/thumbnail'"/>
				</tal:block>
					<ul>
						<li tal:condition="recipe/getPeopleNumber">
							<strong>${trans: m.recipes.document.recipe.peoplenumber, ucf, lab}</strong> ${recipe/getPeopleNumber}
						</li>
						<li tal:condition="recipe/getDifficulty">
							<strong>${trans: m.recipes.document.recipe.difficulty, ucf, lab}</strong> ${recipe/getDifficultyLabelAsHtml}
						</li>
						<li tal:condition="recipe/getCost">
							<strong>${trans: m.recipes.document.recipe.cost, ucf, lab}</strong> ${recipe/getCostLabelAsHtml}
						</li>
						<li tal:condition="recipe/getVegetarian">
							<strong>${trans: m.recipes.fo.vegetarian,ucf}</strong>
						</li>
					</ul>
			
				<div class="cleaner"></div>
				<div class="small">
					${trans: m.recipes.fo.add-date, ucf} ${datetime: recipe/getUICreationdate}
				</div>
			</div>
		</li>
	</tal:block>
</ol>
<div change:paginator="recipes"/>


Mise en oeuvre

Pour rendre le bloc accessible, on se rend en back office, nous allons créer une rubrique “Recettes” que nous allons ajouter au menu principal. Nous crééerons une page dans la rubrique et nous y mettrons le bloc. Une fois la page enregistrée on lui attribuera le tag “Liste des recettes”.

Screenshot du résultat

Bloc de liste BO
Bloc de liste en back office
Bloc de liste FO
Bloc de liste en front office
devguide/createmodule/createblocklist.txt · Dernière modification: 2017/01/19 14:54 (modification externe)