Nouveau plugin : trier les champs d'un objet

Note de ce sujet :
  • Moyenne : 0 (0 vote(s))
  • 1
  • 2
  • 3
  • 4
  • 5
#1
Pour cmsms 1.11
Basé sur le plugin de Bredt : http://www.cmsmadesimple.fr/forum/viewtopic.php?id=3769

Vous avez une page "artistes et vous avez créé des pages enfants avec le nom de tous ces artistes.
Vous souhaiteriez créer une navigation latérale qui affiche tous les noms des artistes dans l'ordre alphabétique (ou inverse) sans devoir réorganiser l'ordre des pages enfants dans l'administration ?

Vous souhaitez afficher les news dans l'ordre alphabétique inverse des titres ?

Vous souhaitez afficher les "définitions de champs" des news dans l'ordre des 'id', du 'name', du 'type' ou encore de sa 'value' ?

Vous souhaitez ordonner les array d'un objet ?

Ce plugin est votre meilleur ami Smile

Tutoriel :
En premier lieu, vous téléchargez le plugin que vous placerez dans le dossier plugins
OU
code à coller dans un fichier (modifier.sort_object_array.php) que vous placerez dans le répertoire plugins.
Code :
[== Indéfini ==]
<?php
/**
* Smarty plugin
*/

/**
* Smarty sort_object_array modifier plugin
*
* Type:     modifier
* Name:     sort_object_array
* Help : http://www.cmsmadesimple.fr/forum/viewtopic.php?id=4439
* @link
* @author   Jean le Chauve
* @param array
* @param string
* @return array
* put '-' before the value for inverse
*/

function smarty_cms_modifier_sort_object_array($objArray, $sortby='')
{
    if (!is_array($objArray)) {
        die("not array, you cannot use the modificator sort_object_array with this variable");
    }
    $dir = '>';
    if ($sortby[0] == '-')
    {
        $sortby = substr($sortby, 1);
        $dir = '<';
    }
    $cmp = create_function('$a,$b', 'return strtolower($a->'.$sortby.')'.$dir.'strtolower($b->'.$sortby.');');    
    usort($objArray, $cmp);
    return $objArray;
}
?>

1) Explication pour la gestion de menu :
Copiez le gabarit de menu de votre sidebar et collez-le dans un nouveau que vous appellerez "artistes"
Code :
{if $count > 0}
<ul>
{foreach from=$nodelist|sort_object_array:'menutext' item=node}
{if $node->depth > $node->prevdepth}
{repeat string="<ul>" times=$node->depth-$node->prevdepth}
{elseif $node->depth < $node->prevdepth}
{repeat string="</li></ul>" times=$node->prevdepth-$node->depth}
</li>
{elseif $node->index > 0}</li>
{/if}
{if $node->parent == true or ($node->current == true and $node->haschildren == true)}
<li class="menuactive menuparent"><a class="menuactive menuparent" href="{$node->url}"><span>{$node->menutext}</span></a>
{elseif $node->haschildren == true and $node->type != 'sectionheader' and $node->type != 'separator'}
<li class="parent"><a class="parent" href="{$node->url}"><span>{$node->menutext}</span></a>
{elseif $node->current == true}
<li class="currentpage"><span>{$node->menutext}</span>
{elseif $node->type == 'sectionheader'}
<li class="sectionheader"><span>{$node->menutext}</span>
{elseif $node->type == 'separator'}
<li class="separator" style="list-style-type: none;"> <hr />
{else}
<li><a href="{$node->url}"><span>{$node->menutext}</span></a>
{/if}
{/foreach}
{repeat string="</li></ul>" times=$node->depth-1}</li>
</ul>
{/if}
Vous n'avez qu'à ajouter le modificateur du plugin (|sort_object_array:'menutext') sur le premier foreach (ligne 3)
Je l'ai déjà fait pour vous Wink
Ensuite, vous ouvrez votre gabarit de page et vous collez le code suivant dans votre sidebar
Code :
[== Indéfini ==]
<div class="pageSidebar">            
    <span class='titlesidebar'>Tous les artistes</span>
    {menu template="artistes" start_level="2"}
</div>

2) Explications pour afficher le sommaire des news dans l'ordre alphabétique inverse des titres :
Cherchez la ligne
Code :
{foreach from=$items item='entry'}
et ajoutez le modificateur :
Code :
[== Indéfini ==]
{foreach from=$items|sort_object_array:'-title' item='entry'}
Vous avez vu ? Il y a un - devant le champ à trier.
Un - devant le nom du champ à trier inverse l'ordre de tri (s'il n'y a que le nom on obtient l'ordre ascendant).

3) Explications pour trier les définitions de champ :
Ouvrez votre gabarit de détail des news et ajoutez le modificateur :
Code :
[== Indéfini ==]
{if isset($entry->fields)}
  {foreach from=$entry->fields|sort_object_array:'name' item='field'}
     <div class="NewsDetailField">
Pour connaître les valeurs possibles, placez {$entry->fields|var_dump}
et vous obtiendrez plus ou moins ceci :
array (size=5)
'image' =>
object(news_field)[157]
private '_data' =>
array (size=7)
'id' => string '1' (length=1)
'name' => string 'image' (length=5)
'type' => string 'textbox' (length=7)
'max_length' => string '255' (length=3)
'item_order' => string '1' (length=1)
'public' => string '1' (length=1)
'value' => string 'eee' (length=3)
'champs2' =>
object(news_field)[153]
private '_data' =>
array (size=7)
'id' => string '2' (length=1)
'name' => string 'champs2' (length=7)
'type' => string 'textbox' (length=7)
'max_length' => string '255' (length=3)
'item_order' => string '2' (length=1)
'public' => string '1' (length=1)
'value' => string 'ceci est e champs 2' (length=19)
'champs3' =>
...

Enjoy Smile
Répondre
#1
Pour cmsms 1.11
Basé sur le plugin de Bredt : http://www.cmsmadesimple.fr/forum/viewtopic.php?id=3769

Vous avez une page "artistes et vous avez créé des pages enfants avec le nom de tous ces artistes.
Vous souhaiteriez créer une navigation latérale qui affiche tous les noms des artistes dans l'ordre alphabétique (ou inverse) sans devoir réorganiser l'ordre des pages enfants dans l'administration ?

Vous souhaitez afficher les news dans l'ordre alphabétique inverse des titres ?

Vous souhaitez afficher les "définitions de champs" des news dans l'ordre des 'id', du 'name', du 'type' ou encore de sa 'value' ?

Vous souhaitez ordonner les array d'un objet ?

Ce plugin est votre meilleur ami Smile

Tutoriel :
En premier lieu, vous téléchargez le plugin que vous placerez dans le dossier plugins
OU
code à coller dans un fichier (modifier.sort_object_array.php) que vous placerez dans le répertoire plugins.
Code :
[== Indéfini ==]
<?php
/**
* Smarty plugin
*/

/**
* Smarty sort_object_array modifier plugin
*
* Type:     modifier
* Name:     sort_object_array
* Help : http://www.cmsmadesimple.fr/forum/viewtopic.php?id=4439
* @link
* @author   Jean le Chauve
* @param array
* @param string
* @return array
* put '-' before the value for inverse
*/

function smarty_cms_modifier_sort_object_array($objArray, $sortby='')
{
    if (!is_array($objArray)) {
        die("not array, you cannot use the modificator sort_object_array with this variable");
    }
    $dir = '>';
    if ($sortby[0] == '-')
    {
        $sortby = substr($sortby, 1);
        $dir = '<';
    }
    $cmp = create_function('$a,$b', 'return strtolower($a->'.$sortby.')'.$dir.'strtolower($b->'.$sortby.');');    
    usort($objArray, $cmp);
    return $objArray;
}
?>

1) Explication pour la gestion de menu :
Copiez le gabarit de menu de votre sidebar et collez-le dans un nouveau que vous appellerez "artistes"
Code :
{if $count > 0}
<ul>
{foreach from=$nodelist|sort_object_array:'menutext' item=node}
{if $node->depth > $node->prevdepth}
{repeat string="<ul>" times=$node->depth-$node->prevdepth}
{elseif $node->depth < $node->prevdepth}
{repeat string="</li></ul>" times=$node->prevdepth-$node->depth}
</li>
{elseif $node->index > 0}</li>
{/if}
{if $node->parent == true or ($node->current == true and $node->haschildren == true)}
<li class="menuactive menuparent"><a class="menuactive menuparent" href="{$node->url}"><span>{$node->menutext}</span></a>
{elseif $node->haschildren == true and $node->type != 'sectionheader' and $node->type != 'separator'}
<li class="parent"><a class="parent" href="{$node->url}"><span>{$node->menutext}</span></a>
{elseif $node->current == true}
<li class="currentpage"><span>{$node->menutext}</span>
{elseif $node->type == 'sectionheader'}
<li class="sectionheader"><span>{$node->menutext}</span>
{elseif $node->type == 'separator'}
<li class="separator" style="list-style-type: none;"> <hr />
{else}
<li><a href="{$node->url}"><span>{$node->menutext}</span></a>
{/if}
{/foreach}
{repeat string="</li></ul>" times=$node->depth-1}</li>
</ul>
{/if}
Vous n'avez qu'à ajouter le modificateur du plugin (|sort_object_array:'menutext') sur le premier foreach (ligne 3)
Je l'ai déjà fait pour vous Wink
Ensuite, vous ouvrez votre gabarit de page et vous collez le code suivant dans votre sidebar
Code :
[== Indéfini ==]
<div class="pageSidebar">            
    <span class='titlesidebar'>Tous les artistes</span>
    {menu template="artistes" start_level="2"}
</div>

2) Explications pour afficher le sommaire des news dans l'ordre alphabétique inverse des titres :
Cherchez la ligne
Code :
{foreach from=$items item='entry'}
et ajoutez le modificateur :
Code :
[== Indéfini ==]
{foreach from=$items|sort_object_array:'-title' item='entry'}
Vous avez vu ? Il y a un - devant le champ à trier.
Un - devant le nom du champ à trier inverse l'ordre de tri (s'il n'y a que le nom on obtient l'ordre ascendant).

3) Explications pour trier les définitions de champ :
Ouvrez votre gabarit de détail des news et ajoutez le modificateur :
Code :
[== Indéfini ==]
{if isset($entry->fields)}
  {foreach from=$entry->fields|sort_object_array:'name' item='field'}
     <div class="NewsDetailField">
Pour connaître les valeurs possibles, placez {$entry->fields|var_dump}
et vous obtiendrez plus ou moins ceci :
array (size=5)
'image' =>
object(news_field)[157]
private '_data' =>
array (size=7)
'id' => string '1' (length=1)
'name' => string 'image' (length=5)
'type' => string 'textbox' (length=7)
'max_length' => string '255' (length=3)
'item_order' => string '1' (length=1)
'public' => string '1' (length=1)
'value' => string 'eee' (length=3)
'champs2' =>
object(news_field)[153]
private '_data' =>
array (size=7)
'id' => string '2' (length=1)
'name' => string 'champs2' (length=7)
'type' => string 'textbox' (length=7)
'max_length' => string '255' (length=3)
'item_order' => string '2' (length=1)
'public' => string '1' (length=1)
'value' => string 'ceci est e champs 2' (length=19)
'champs3' =>
...

Enjoy Smile
Répondre
#2
tu t'arrêtes plus Big Grin
Répondre
#2
tu t'arrêtes plus Big Grin
Répondre
#3
It's a summer tuto!
inutile de te demander d'alimenter le wiki?
{SEO}
Inscrivez-vous à notre Newsletter sur le site (colonne de droite, en bas).
Vous appréciez CMSMS et l'aide qui vous est fournie ici, aidez-nous en participant au projet.
Formation CMS Made Simple | Création de site CMS Made Simple.

C'est en se plantant qu'on devient cultivé.
J'ai un string dans l'Array (Paris Hilton)
Répondre
#3
It's a summer tuto!
inutile de te demander d'alimenter le wiki?
{SEO}
Inscrivez-vous à notre Newsletter sur le site (colonne de droite, en bas).
Vous appréciez CMSMS et l'aide qui vous est fournie ici, aidez-nous en participant au projet.
Formation CMS Made Simple | Création de site CMS Made Simple.

C'est en se plantant qu'on devient cultivé.
J'ai un string dans l'Array (Paris Hilton)
Répondre
#4
@ jean

Révision 8229 -- prefilters and postfilters can now be displayed on the listttags ...
http://viewsvn.cmsmadesimple.org/revisio...e&rev=8229
J-C Etiemble v 2.2.xx
Répondre
#4
@ jean

Révision 8229 -- prefilters and postfilters can now be displayed on the listttags ...
http://viewsvn.cmsmadesimple.org/revisio...e&rev=8229
J-C Etiemble v 2.2.xx
Répondre
#5
Merci Jce, j'ai vu (j'avais posté le plugin sur .org en précisant la ligne qui empêchait la publication) : http://forum.cmsmadesimple.org/viewtopic...=7&t=62340
2 heures après, c'était réglé Smile
Par contre, j'ai trouvé un gros bug, donné la solution et mon post a été effacé sans explication ???
Répondre
#5
Merci Jce, j'ai vu (j'avais posté le plugin sur .org en précisant la ligne qui empêchait la publication) : http://forum.cmsmadesimple.org/viewtopic...=7&t=62340
2 heures après, c'était réglé Smile
Par contre, j'ai trouvé un gros bug, donné la solution et mon post a été effacé sans explication ???
Répondre
#6
Citation :Par contre, j'ai trouvé un gros bug, donné la solution et mon post a été effacé sans explication ???
Ha oui ça arrive (m'es arrivé) dans ce cas poste sur le bug tracker
J-C Etiemble v 2.2.xx
Répondre
#6
Citation :Par contre, j'ai trouvé un gros bug, donné la solution et mon post a été effacé sans explication ???
Ha oui ça arrive (m'es arrivé) dans ce cas poste sur le bug tracker
J-C Etiemble v 2.2.xx
Répondre
#7
C'est où ça ?
C'est pour le module fileManager qui est dans le core.
Répondre
#7
C'est où ça ?
C'est pour le module fileManager qui est dans le core.
Répondre
#8
http://dev.cmsmadesimple.org/bug/list/6

Normalement Filemanager n'est pas dans le core . il est livré avec Smile
la page sur la forge existe mais n'est plus ... à jour
J-C Etiemble v 2.2.xx
Répondre
#8
http://dev.cmsmadesimple.org/bug/list/6

Normalement Filemanager n'est pas dans le core . il est livré avec Smile
la page sur la forge existe mais n'est plus ... à jour
J-C Etiemble v 2.2.xx
Répondre
#9
J'ai refait le post sur .org : http://forum.cmsmadesimple.org/viewtopic...66#p283966
Répondre
#9
J'ai refait le post sur .org : http://forum.cmsmadesimple.org/viewtopic...66#p283966
Répondre
#10
Salut Jean le Chauve,
Chui très honoré que tu te sois basé sur mon ptit plugin :p
Juste quelques remarques :
- ton post n'existe plus sur .org ! Sad
- j'aurais du faire une remarque sur mon post, mais faire des comparaisons avec < et > ce n'est pas ce qu'il y a de mieux (maj, min, accents ...), y'a des fonctions php de comparaison de chaine qui sont assez puissante comme strcoll()

Bredt Cool
Répondre
#10
Salut Jean le Chauve,
Chui très honoré que tu te sois basé sur mon ptit plugin :p
Juste quelques remarques :
- ton post n'existe plus sur .org ! Sad
- j'aurais du faire une remarque sur mon post, mais faire des comparaisons avec < et > ce n'est pas ce qu'il y a de mieux (maj, min, accents ...), y'a des fonctions php de comparaison de chaine qui sont assez puissante comme strcoll()

Bredt Cool
Répondre
#11
Salut Bredt Smile
Le post n'existe plus, mais n'avais rien à voir avec le plugin ; il s'agissait d'un d'une proposition de code pour le bêta-test.
strcoll() est une excellente idée. Vas-y, lâche-toi, tu es à l'origine du plugin Smile
Répondre
#11
Salut Bredt Smile
Le post n'existe plus, mais n'avais rien à voir avec le plugin ; il s'agissait d'un d'une proposition de code pour le bêta-test.
strcoll() est une excellente idée. Vas-y, lâche-toi, tu es à l'origine du plugin Smile
Répondre
#12
Heu là pour l'instant, j'ai plus rien en stock !!! :/
Bredt Cool
Répondre
#12
Heu là pour l'instant, j'ai plus rien en stock !!! :/
Bredt Cool
Répondre
#13
Bonjour Jean,
je reviens sur ce topic car je tente vainement de classer mes catégories pas ordre chronologique décroissant.

J'ai créé le fichier modifier.sort_object_array.php comme tu le propose, puis ai rentré dans mon gabarit de catégories :

Code :
[== HTML ==]
[== Indéfini ==]
<ul class="list1">
{foreach from=$cats|sort_object_array:'-news_category_name' item=node}
<li>
    <div class="lien_article">
    <a href="{$node.url}">{$node.news_category_name}</a>
    </div>
</li>
{/foreach}
</ul>

Résultat j'ai une suite d'une vingtaine de lignes en front :
Notice: Trying to get property of non-object in F:\WEB\wamp\www\annevaleriedupond.com\plugins\modifier.sort_object_array.php(32) : runtime-created function on line 1

Puis mes catégories dans le désordre :

Archives 2012
Archives 2013
Archives 2011
Archives 2010
Archives 2009

Saurais tu me dire ce que je dois modifier pour obtenir cette affichage :

Archives 2013
Archives 2012
Archives 2011
Archives 2010
Archives 2009

Merci
Répondre
#13
Bonjour Jean,
je reviens sur ce topic car je tente vainement de classer mes catégories pas ordre chronologique décroissant.

J'ai créé le fichier modifier.sort_object_array.php comme tu le propose, puis ai rentré dans mon gabarit de catégories :

Code :
[== HTML ==]
[== Indéfini ==]
<ul class="list1">
{foreach from=$cats|sort_object_array:'-news_category_name' item=node}
<li>
    <div class="lien_article">
    <a href="{$node.url}">{$node.news_category_name}</a>
    </div>
</li>
{/foreach}
</ul>

Résultat j'ai une suite d'une vingtaine de lignes en front :
Notice: Trying to get property of non-object in F:\WEB\wamp\www\annevaleriedupond.com\plugins\modifier.sort_object_array.php(32) : runtime-created function on line 1

Puis mes catégories dans le désordre :

Archives 2012
Archives 2013
Archives 2011
Archives 2010
Archives 2009

Saurais tu me dire ce que je dois modifier pour obtenir cette affichage :

Archives 2013
Archives 2012
Archives 2011
Archives 2010
Archives 2009

Merci
Répondre
#14
Le message d'erreur t'explique le problème : $cats n'est pas un objet, mais l'array de l'objet $entry.
Plus simple : interverti l'id de 2012 avec 2013 dans la base de données (cms_module_news_categories), ou supprime archives 2013 puis recrée-la (si elle ne contient pas d'article).
Répondre
#14
Le message d'erreur t'explique le problème : $cats n'est pas un objet, mais l'array de l'objet $entry.
Plus simple : interverti l'id de 2012 avec 2013 dans la base de données (cms_module_news_categories), ou supprime archives 2013 puis recrée-la (si elle ne contient pas d'article).
Répondre
#15
Je viens d'essayé intervertir l'id en BdD ... pas de changement en front.
J'ai essayé d'intervertir la "hierarchy" ... la c'était tout bon en front (bien que j'ai toujours les lignes d'erreurs).
J'ai voulu ajouter une catégorie Archives 2014 ... et la patatra :

Archives 2012
Archives 2014
Archives 2013
Archives 2011
Archives 2009
Archives 2010

et toujours les lignes d'erreurs.

Je comprends pas ce qu'il se passe ... une autre idée ?
Répondre
#15
Je viens d'essayé intervertir l'id en BdD ... pas de changement en front.
J'ai essayé d'intervertir la "hierarchy" ... la c'était tout bon en front (bien que j'ai toujours les lignes d'erreurs).
J'ai voulu ajouter une catégorie Archives 2014 ... et la patatra :

Archives 2012
Archives 2014
Archives 2013
Archives 2011
Archives 2009
Archives 2010

et toujours les lignes d'erreurs.

Je comprends pas ce qu'il se passe ... une autre idée ?
Répondre
#16
Je t'ai dit que ce plugin ne fonctionne que pour trier un objet (ce qui n'est pas le cas de $cats).
Quel est l'appel de balise news que tu exécute ?
L'utilisation des paramètres sortby="news_category_name" et sortasc=false donneraient-ils la bonne configuration, tout simplement ? Sinon, crée une udt avec une requête sql adéquate ou une fonction qui trie un tableau multidimensionnel.
Si ça ne marche pas, ouvre un nouveau post pour ne pas polluer celui-ci qui n'est pas en rapport avec ton cas.
Répondre
#16
Je t'ai dit que ce plugin ne fonctionne que pour trier un objet (ce qui n'est pas le cas de $cats).
Quel est l'appel de balise news que tu exécute ?
L'utilisation des paramètres sortby="news_category_name" et sortasc=false donneraient-ils la bonne configuration, tout simplement ? Sinon, crée une udt avec une requête sql adéquate ou une fonction qui trie un tableau multidimensionnel.
Si ça ne marche pas, ouvre un nouveau post pour ne pas polluer celui-ci qui n'est pas en rapport avec ton cas.
Répondre
#17
sortby="news_category_name" et sortasc=false ne renvois que des erreurs.
Désolé Jean, je ne suis qu'un simple webdesigner ... et je ne sais pas faire ce que tu me propose.
L'appel que je fais depuis le "gabarit de sommaire d'article" est {news action="browsecat"}
Puis j'ai ce code dans "gabarit de catégories" :
Code :
[== HTML ==]
<ul class="list1">
{foreach from=$cats item=node}
{if $node.count > 0}
<li>
    <div class="lien_article">
    <a href="{$node.url}">{$node.news_category_name}</a>
    </div>
</li>
{/if}
{/foreach}
</ul>
Je pensais que ton post pouvait concerner également le tri des catégories news ... mais ça n'a pas l'air d'être le cas, je vais donc arrêter de "polluer" ton post.
C'est pas grave, je vais rester avec mes catégories comme ça.
Merci quand même.
Répondre
#17
sortby="news_category_name" et sortasc=false ne renvois que des erreurs.
Désolé Jean, je ne suis qu'un simple webdesigner ... et je ne sais pas faire ce que tu me propose.
L'appel que je fais depuis le "gabarit de sommaire d'article" est {news action="browsecat"}
Puis j'ai ce code dans "gabarit de catégories" :
Code :
[== HTML ==]
<ul class="list1">
{foreach from=$cats item=node}
{if $node.count > 0}
<li>
    <div class="lien_article">
    <a href="{$node.url}">{$node.news_category_name}</a>
    </div>
</li>
{/if}
{/foreach}
</ul>
Je pensais que ton post pouvait concerner également le tri des catégories news ... mais ça n'a pas l'air d'être le cas, je vais donc arrêter de "polluer" ton post.
C'est pas grave, je vais rester avec mes catégories comme ça.
Merci quand même.
Répondre
#18
Djooline,
A moins de travailler pour une boîte qui emploie beaucoup de monde, tu ne vas pas aller très loin en n'étant qu'un "simple webdesigner" si tu souhaites créer seul des sites "personnalisés" : tu as besoin de compétences en PHP et SQL.
Je te conseille de te former un minimum dans ces disciplines.
Je te sens désolé, mais le titre de ce post est explicite : trier les champs d'un objet et tu souhaites trier sur les champs d'un tableau multidimensionnel, ce plugin ne peut pas fonctionner dans ton cas.
Je t'ai donné plusieurs solutions ; pour les requêtes SQl, le wiki peut t'aider : http://wiki.cmsmadesimple.fr/wiki/Module_la_bdd.
Il te reste à improviser une solution plus adaptée à tes compétences ou à ouvrir un autre post afin de trouver quelqu'un qui pourrait t'aider.
Répondre
#18
Djooline,
A moins de travailler pour une boîte qui emploie beaucoup de monde, tu ne vas pas aller très loin en n'étant qu'un "simple webdesigner" si tu souhaites créer seul des sites "personnalisés" : tu as besoin de compétences en PHP et SQL.
Je te conseille de te former un minimum dans ces disciplines.
Je te sens désolé, mais le titre de ce post est explicite : trier les champs d'un objet et tu souhaites trier sur les champs d'un tableau multidimensionnel, ce plugin ne peut pas fonctionner dans ton cas.
Je t'ai donné plusieurs solutions ; pour les requêtes SQl, le wiki peut t'aider : http://wiki.cmsmadesimple.fr/wiki/Module_la_bdd.
Il te reste à improviser une solution plus adaptée à tes compétences ou à ouvrir un autre post afin de trouver quelqu'un qui pourrait t'aider.
Répondre


Atteindre :


Utilisateur(s) parcourant ce sujet : 1 visiteur(s)