Outils pour utilisateurs

Outils du site


Panneau latéral

ref:backoffice:filters

Ceci est une ancienne révision du document !


Filtres

Généralités

  • module non-visible en backoffice
  • apporte le nécessaire pour permettre d'intégrer un champ de type query dans le formulaire backoffice d'un document
  • exemple d'utilisation : module comptes clients (groupes dynamiques), module commandes (dossiers intelligents)
  • un filtre peut implémenter l'une, l'autre ou l(ensemble des deux méthodes suivantes :
    • getQuery permettant de requêter les documents qui satisfont le filtre
    • checkValue permettant de valider qu'un document donné satisfait le filtre

Intégration d'un champ de type query dans un document Change

Dans le modèle du document

Ajouter une propriété de type Lob dans le modèle du document.

Exemple :

<add name="query" type="Lob" min-occurs="1" />

Dans le formulaire backoffice du document

Dans les fichier où cette propriété est éditable, c'est à dire, selon les cas : create.xml et/ou properties.xml et/ou localization.xml, spécifier pour cette propriété les deux attributs suivants :

  • type : doit prendre la valeur query (le binding cQueryField du module filter sera alors utilisé)
  • listid : permet d'indiquer le modèle sur lequel on veut effectuer la requête sous la forme “module/document” et optionnellement spécifier quelles méthodes sont requises sur le filtre

Exemples :

<!-- accepte les filtres sur les comptes clients -->
<field name="query1" type="query" listid="customer/customer"/>
<!-- accepte les filtres de sur les comptes clients sur lesquels à la fois getQuery et checkValue sont implémentés -->
<field name="query2" type="query" listid="customer/customer::getQuery,checkValue"/>

Définition des filtres

Un champ du formulaire de type query va permettre de construire une requête à l'aide de différents filtres. Ces filtres doivent être définis par code dans n'importe quel module : la commande change.php compile-document-filters se charge de retrouver l'ensemble des filtres et de les grouper selon le modèle sur lequel ils portent. Un filtre est une classe PHP à placer dans le dossier monModule/persistentdocument/filters (seuls ces dossiers sont scannés par la commande de compilation des filtres).

Les filtres doivent implémenter l'interface f_persistentdocument_DocumentFilter qui définit les différentes méthodes nécessaires. Une implémentation par défaut d'un certain nombre de ces méthodes est disponible, il s'agit de la classe f_persistentdocument_DocumentFilterImpl. Dans la majorité des cas, c'est cette classe qu'étendra le filtre. Les méthodes à implémenter seront alors les suivantes :

  • getDocumentModelName() : méthode statique qui renvoie simplement le modèle sur lequel ce filtre s'applique, sous la forme modules_monModule/monDocument.
  • __construct() : le constructeur se charge de définir et configurer les différents paramètres du filtre. Ces paramètres peuvent être de deux types différents :
    • restriction (f_persistentdocument_DocumentFilterRestrictionParameter) : l'utilisateur pourra paramétrer une restriction complète : type de restriction, champ sur lequel elle porte et valeur. On peut spécifier la liste des champs et des restrictions disponibles pour un paramètre donné ou bien les spécifier en dur (ils ne seront alors pas modifiable dans l'interface)
    • valeur (f_persistentdocument_DocumentFilterValueParameter) : l'utilisateur pourra simplement saisir une valeur qui sera ensuite utilisée pour écrire la requête. Le champ proposé sera mono-valué et pourra être de n'importe quel type standard (entier, flottant, document, chaine…). On définit ce type à l'aide d'une BeanPropertyInfo qui peut être configurée à la main ou, s'il s'agit d'une propriété d'un document, récupérée directement d'un modèle. Attention, les contraintes de validation définies ne seront pas prises en compte, le champ sera juste obligatoire et validé avec via les validateurs par défaut du champ
  • getQuery() : cette méthode renvoie la query (instance de f_persistentdocument_criteria_Query) correspondant au filtre. Celle-ci n'est supposée être appelée que sur un filtre où tous les paramètres ont été remplis
  • checkValue($value) : cette méthode prend en paramètre une instance de document et renvoie true si elle satisfait le filtre, false sinon

On trouve aussi dans certains filtres d'autres méthodes qu'a priori on n'implémentera pas sur un filtre spécifique d'un projet :

  • isHidden() : si elle retourne true, ce filtre ne sera pas sélectionnable dans les listes (utilisé pour déprécier des filtres sans pour autant casser les documents qui l'utilisent déjà)
  • getAliases() : renvoie un tableau de noms de classes considérées comme des alias de ce filtre. Ces noms correspondent à des classes qui n'existent pas physiquement, si ces noms sont retrouvés dans la configuration d'un document, un instance de ce filtre sera utilisée (utilisé lors du renommage de la classe d'un filtre, par exemple pour le changer de module, sans casser les documents qui l'utilisent déjà)

Exemples :

  • filtre sur les propriété d'un sous-document :

class customer_BillingAddressFilter extends f_persistentdocument_DocumentFilterImpl
{
	public function __construct()
	{
		$amountParameter = f_persistentdocument_DocumentFilterRestrictionParameter::getNewInstance();
		$amountParameter->setAllowedPropertyNames(array(
			'modules_customer/billingaddress.creationdate',
			'modules_customer/billingaddress.title',
			'modules_customer/billingaddress.firstname',
			'modules_customer/billingaddress.lastname',
			'modules_customer/billingaddress.email',
			'modules_customer/billingaddress.company',
			'modules_customer/billingaddress.addressLine1',
			'modules_customer/billingaddress.addressLine2',
			'modules_customer/billingaddress.addressLine3',
			'modules_customer/billingaddress.zipCode',
			'modules_customer/billingaddress.city',
			'modules_customer/billingaddress.province',
			'modules_customer/billingaddress.country',
			'modules_customer/billingaddress.phone',
			'modules_customer/billingaddress.fax',
		));
		$this->setParameters(array('field' => $amountParameter));
	}
	
	/**
	 * @return String
	 */
	public static function getDocumentModelName()
	{
		return 'modules_customer/customer';
	}

	/**
	 * @return f_persistentdocument_criteria_Query
	 */
	public function getQuery()
	{
		$query = customer_CustomerService::getInstance()->createQuery();
		$query->createCriteria('billingAddress')->add($this->getParameter('field')->getValueForQuery());
		return $query;
	}
}

  • filtre sur le résultat d'une projection :

class customer_UsedCouponCountFilter extends f_persistentdocument_DocumentFilterImpl
{
	public function __construct()
	{
		$parameters = array();

		$info = new BeanPropertyInfoImpl('count', 'Integer');
		$parameter = f_persistentdocument_DocumentFilterRestrictionParameter::getNewHavingInstance($info);
		$parameters['count'] = $parameter;
		
		$this->setParameters($parameters);
	}

	/**
	 * @return String
	 */
	public static function getDocumentModelName()
	{
		return 'modules_customer/customer';
	}

	/**
	 * @return f_persistentdocument_criteria_Query
	 */
	public function getQuery()
	{
		$query = customer_CustomerService::getInstance()->createQuery()->setFetchColumn('this');
		$query->createCriteria('usedCoupon')->setProjection(Projections::rowCount('count'));
		$query->having($this->getParameter('count')->getValueForQuery());
		return $query;
	}
}

  • filtre construit à partir de valeurs :

class customer_LoginFilter extends f_persistentdocument_DocumentFilterImpl
{
	public function __construct()
	{
		$parameters = array();
		
		$info = new BeanPropertyInfoImpl('mode', 'String');
		$info->setLabelKey('mode de recherche');
		$info->setListId('modules_filter/matchmodes');
		$parameter = new f_persistentdocument_DocumentFilterValueParameter($info);
		$parameters['mode'] = $parameter;
		
		$info = new BeanPropertyInfoImpl('code', 'String');
		$info->setLabelKey('chaine recherchée');
		$parameter = new f_persistentdocument_DocumentFilterValueParameter($info);
		$parameters['code'] = $parameter;
		
		$this->setParameters($parameters);
	}

	/**
	 * @return String
	 */
	public static function getDocumentModelName()
	{
		return 'modules_customer/customer';
	}

	/**
	 * @return f_persistentdocument_criteria_Query
	 */
	public function getQuery()
	{
		$dfs = f_persistentdocument_DocumentFilterService::getInstance();
		$mode = $dfs->getMatchMode($this->getParameter('mode')->getValueForQuery());
		$query = customer_CustomerService::getInstance()->createQuery();
		$query->createCriteria('user')->add(Restrictions::like('login', $this->getParameter('code')->getValueForQuery(), $mode, true));
		return $query;
	}
}

  • filtre implémentant à la fois getQuery() et checkValue() :

class order_ShopOrderFilter extends f_persistentdocument_DocumentFilterImpl
{
	public function __construct()
	{
		$parameters = array();
		
		$info = new BeanPropertyInfoImpl('shop', 'modules_catalog/shop');
		$shopParameter = new f_persistentdocument_DocumentFilterValueParameter($info);
		$parameters['shop'] = $shopParameter;
		$this->setParameters($parameters);
	}
	
	/**
	 * @return String
	 */
	public static function getDocumentModelName()
	{
		return 'modules_order/order';
	}

	/**
	 * @return f_persistentdocument_criteria_Query
	 */
	public function getQuery()
	{
		$shopIds =  DocumentHelper::getIdArrayFromDocumentArray($this->getParameter('shop')->getValueForQuery());
		return order_OrderService::getInstance()->createQuery()->add(Restrictions::in('shopId', $shopIds));
	}
	
	/**
	 * @param customer_persistentdocument_customer $value
	 * @return boolean
	 */
	public function checkValue($value)
	{
		if ($value instanceof order_persistentdocument_order)
		{
			$shopIds =  DocumentHelper::getIdArrayFromDocumentArray($this->getParameter('shop')->getValueForQuery());
			return in_array($value->getShopId(), $shopIds);
		}
		return false;
	}
}

  • autres exemples disponibles dans les modules comptes clients (customer) ou commandes (order).

Exploiter un champ de type ''query''

Ce qui est stocké en base dans la propriété de type query est une représentation JSON de l'ensemble des filtres sélectionnés. Pour exploiter cet ensemble de filtre, on fait appel au service f_persistentdocument_DocumentFilterService qui dispose des méthodes :

  • checkValueFromJson($json, $value) : renvoie un booléen disant si $value satisfait l'ensemble de filtres décrits par $json
  • getQueryIntersectionFromJson($json) : renvoie un instance de f_persistentdocument_criteria_QueryIntersection ou f_persistentdocument_criteria_QueryUnion qui sont respectivement une intersection ou une union de plusieurs query. On ne peut pas ajouter de restriction ou appliquer des tris ou des projections à cette instance, comme on peut le faire sur une query. Tout ce que l'on peut faire c'est :
    • ajouter une autre query (méthode add($query)) : pour ajouter un filtre à cette intersection. Attention, cette query doit impérativement porter sur un modèle compatible avec celui de l'ensemble des query déjà incluses dans l'intersection.
    • récupérer les documents (méthode find()) : récupère les instances des documents répondant aux critères de l'ensemble des query de l'intersection.
    • récupérer les ids des documents (méthode findIds()) : récupère les identifiants des documents répondant aux critères de l'ensemble des query de l'intersection.

Exemple de validation d'un document :

	/**
	 * @param customer_persistentdocument_dynamiccustomergroup $group
	 * @param customer_persistentdocument_customer $customer
	 * @return boolean
	 */
	protected function doIsMember($group, $customer)
	{
		return f_persistentdocument_DocumentFilterService::getInstance()->checkValueFromJson($group->getQuery(), $customer);
	}

Exemple de requêtage :

	/**
	 * @param customer_persistentdocument_dynamiccustomergroup
	 * @return customer_persistentdocument_customer[]
	 */
	protected function doGetMembers($group)
	{
		$queryIntersection = f_persistentdocument_DocumentFilterService::getInstance()->getQueryIntersectionFromJson($group->getQuery());
		return $queryIntersection->find();
	}
		
	/**
	 * @param customer_persistentdocument_dynamiccustomergroup
	 * @return integer[]
	 */
	protected function doGetMemberIds($group)
	{
		$queryIntersection = f_persistentdocument_DocumentFilterService::getInstance()->getQueryIntersectionFromJson($group->getQuery());
		return $queryIntersection->findIds();
	}

Filtre ne portant pas sur un document

Il est possible de faire des filtres ne portant par sur un document (par exemple sur un panier). Ceci fonctionne globalement de la même manière, avec les spécificités et restrictions suivantes :

  • on ne peut faire de query que sur un document, implémenter la méthode getQuery n'a donc pas de sens dans ce cas

La mise en œuvre a aussi quelques spécificités :

  • dans les éditeurs de documents, on déclare des propriétés sur ce type de filtres avec le type objectfilter au lieu de query

Exemple :

<field name="query" type="objectfilter" allow="order/cart::checkValue" />

  • la méthode getDocumentModelName du filtre

Exemple :

	/**
	 * @return string
	 */
	public static function getDocumentModelName()
	{
		return 'order/cart';
	}

ref/backoffice/filters.1326186260.txt.gz · Dernière modification: 2017/01/19 14:54 (modification externe)