Dotclear

Vous n'êtes pas identifié(e).

Annonce

#26 2016-05-18 15:55:34

Welsh
Membre
Inscription : 2011-12-28

Re : [plugin mrvbCustomWidgets] support et discussion

Je vais essayer de prendre un peu de temps pour regarder le code pour d'abord le comprendre :-) et voir ce qui peut être fait (si j'y arrive, je ne préjuge pas de tes capacités :-) )

Hors ligne

#27 2016-05-18 15:58:22

Welsh
Membre
Inscription : 2011-12-28

Re : [plugin mrvbCustomWidgets] support et discussion

J'ai pour le moment changé le niveau max (passé de 1 à 2) et on obtient le résultat en ligne (http://histoire.gallois.info).
On voit qu'il y a (a priori) un appel de trop en récursivité.
Je creuse...

Hors ligne

#28 2016-05-18 16:39:37

Philippe
Stagiaire
Lieu : Toulon
Inscription : 2004-06-13
Site Web

Re : [plugin mrvbCustomWidgets] support et discussion

Il me semble qu'il manque, dans le fichier mrvbCustomWidgets/_public.php la partie qui contrôle le niveau d'imbrication de la catégorie.

Dans dotclear/plugins/widgets/_widget_functions.php la fonction qui génère la liste des catégories utilise $rs->level pour créer les <ul> et <li> imbriqués.

Hors ligne

#29 2016-05-18 17:51:03

adjaya
Membre
Lieu : Provence - Luberon
Inscription : 2006-09-05
Site Web

Re : [plugin mrvbCustomWidgets] support et discussion

Welsh a écrit :

On voit qu'il y a (a priori) un appel de trop en récursivité.
Je creuse...

petite précision: le principe de construction de l'arbre hiérarchique des catégories n'est justement pas récursif !


Photo, Art et Création Numérique : http://benoit-grelier.photo7.fr/

Hors ligne

#30 2016-05-18 19:39:29

Welsh
Membre
Inscription : 2011-12-28

Re : [plugin mrvbCustomWidgets] support et discussion

adjaya a écrit :
Welsh a écrit :

On voit qu'il y a (a priori) un appel de trop en récursivité.
Je creuse...

petite précision: le principe de construction de l'arbre hiérarchique des catégories n'est justement pas récursif !

Certes, mais la constitution des niveaus de sous-catégories demandé peut l'être dans la construction de l'algorithme :
- récupération des catégories de 1er niveau
- pour chacune, appel de la même fonction
- on boucle pour avoir le nombre de niveau demandé.

Après il faut arriver aux raffinements mis en place par Mirovinbien : exclusion d'une catégorie...

Il me semble (première lecture) que l'algorithme mis en place par Mirovinbien consiste à tout récupérer et faire le tri.

J'avoue que je n'ai pas regardé les API Dotclear dans le détail, mais je pense que la fonction pour récupérer les sous-catégories d'une catégorie existe.

Comme je l'ai dit, ce sont mes premières impressions. Il faut que je creuse...

Hors ligne

#31 2016-05-19 03:16:11

Mirovinben
M comme Mathusalem
Lieu : Dole (Jura)
Inscription : 2007-02-06
Site Web

Re : [plugin mrvbCustomWidgets] support et discussion

Welsh a écrit :

Je vais essayer de prendre un peu de temps pour regarder le code pour d'abord le comprendre :-) et voir ce qui peut être fait (si j'y arrive, je ne préjuge pas de tes capacités :-) )

Pas de pb, mes capacités vont en diminuant (le "privilège" de l'âge) et je ne demande qu'à apprendre.

Philippe a écrit :

Il me semble qu'il manque, dans le fichier mrvbCustomWidgets/_public.php la partie qui contrôle le niveau d'imbrication de la catégorie.

Dans dotclear/plugins/widgets/_widget_functions.php la fonction qui génère la liste des catégories utilise $rs->level pour créer les <ul> et <li> imbriqués.

Pourtant la fonction mrvb_SubCategories($w) utilise $rs->level...

public static function mrvb_SubCategories($w)
{
	global $core, $_ctx;
	if ($w->offline) {
		return;
	}
	if (($w->homeonly == 1 && $core->url->type != 'default') ||
		($w->homeonly == 2 && $core->url->type == 'default')) {
		return;
	}
	$rs = $core->blog->getCategories();
	if ($rs->isEmpty()) {
		return;
	}
	$exclude = mrvb_ListToArray($w->excludeID);
	$res = ($w->content_only ? '' : '<div class="categories mrvbsubcategories'.($w->CSSclass ? ' '.html::escapeHTML($w->CSSclass) : '').'">');
	if (version_compare(DC_VERSION,'2.7','>=')) {
		$res .= ($w->title ? $w->renderTitle(html::escapeHTML($w->title)) : '');
	} else {
		$res .= ($w->title ? '<h2>'.html::escapeHTML(__($w->title)).'</h2>' : '');
	}
	$max_level = abs((integer) $w->maxlevel);
	$ref_level = $level = $rs->level-1;
	$cat_level = 0;
	while ($rs->fetch()) {
		if (!(in_array($rs->cat_id, $exclude))){
			($w->countsubcat ? $postcount = $rs->nb_total : $postcount = $rs->nb_post);
			$class = ' class="cat'.$rs->cat_id;
			if (($core->url->type == 'category' && $_ctx->categories instanceof record && $_ctx->categories->cat_id == $rs->cat_id)
			|| ($core->url->type == 'post' && $_ctx->posts instanceof record && $_ctx->posts->cat_id == $rs->cat_id)) {
				$class .= ' category-current';
			}
			$class .= '"';
			if ($rs->level > $level) {
				$cat_level += 1;
				$res .= str_repeat('<ul><li'.$class.'>',$rs->level - $level);
			} elseif ($rs->level < $level) {
				$cat_level -= 1;
				$res .= str_repeat('</li></ul>',-($rs->level - $level));
			}
			if (($max_level == 0) || ($cat_level < $max_level + 1)){
				if ($rs->level <= $level) {
					$res .= '</li><li'.$class.'>';
				}
				$res .=	'<a href="'.$core->blog->url.$core->url->getBase('category').'/'.$rs->cat_url.'"';
				if ($w->showcount == 'showballoon'){
					$res .= ' title="'.$postcount.'"';
				}
				$res .= '>'.html::escapeHTML(__($rs->cat_title)).'</a>';
				if ($w->showcount == 'showafter'){
					$res .= ' ('.$postcount.')';
				}
			}
			$level = $rs->level;
		}
	}
	if ($ref_level - $level < 0) {
		$res .= str_repeat('</li></ul>',-($ref_level - $level));
	}
	$res .= ($w->content_only ? '' : '</div>');
	return $res;
}

Hors ligne

#32 2016-05-19 05:53:10

Philippe
Stagiaire
Lieu : Toulon
Inscription : 2004-06-13
Site Web

Re : [plugin mrvbCustomWidgets] support et discussion

Mirovinben a écrit :

Pourtant la fonction mrvb_SubCategories($w) utilise $rs->level...

Désolé, j'avais regardé trop vite et pas vu qu'il y avait deux fonctions : mrvb_Categories et mrvb_SubCategories. J'avoue que je n'ai pas cherché beaucoup, mais pourquoi deux fonctions ?

Hors ligne

#33 2016-05-19 06:32:15

Mirovinben
M comme Mathusalem
Lieu : Dole (Jura)
Inscription : 2007-02-06
Site Web

Re : [plugin mrvbCustomWidgets] support et discussion

Excellent question. Par contre ma réponse va être du genre "je ne m'en souviens plus". Sans doute pour des raisons historiques (les sous-catégories n'étant pas apparues dès les débuts de Dotclear 2) et avant la mise à disposition de la première version "officielle" en février 2010 qui proposait déjà les deux fonctions... Fonctions qui n'ont d'ailleurs pas tout à fait le même usage.

Hors ligne

#34 2016-05-19 06:40:05

Philippe
Stagiaire
Lieu : Toulon
Inscription : 2004-06-13
Site Web

Re : [plugin mrvbCustomWidgets] support et discussion

Après quelques tests en local, le widget Mrvb : sous-categories affiche le même menu que le widget Catégories, à une exception près : les catégories ne comportant pas de billets (mais comportant des entrées d'un autre post_type) sont aussi affichées.

Je ne parviens toutefois pas à reproduire le bug d'indentation des sous-catégories comme chez toi ou Welsh, c'est peut-être lié ?

Hors ligne

#35 2016-05-19 07:20:54

Mirovinben
M comme Mathusalem
Lieu : Dole (Jura)
Inscription : 2007-02-06
Site Web

Re : [plugin mrvbCustomWidgets] support et discussion

Aucune idée... Faut dire aussi que je n'utilise les sous-catégories que dans mon blog de test. D'où mon souhait exprimé plus haut de quelques testeurs supplémentaires... :-)

Hors ligne

#36 2016-05-19 09:20:48

adjaya
Membre
Lieu : Provence - Luberon
Inscription : 2006-09-05
Site Web

Re : [plugin mrvbCustomWidgets] support et discussion

extrait de class.dc.blog.php ( dotclear 2.9.1)

	/**
	Retrieves categories. <var>$params</var> is an associative array which can
	take the following parameters:

	- post_type: Get only entries with given type (default "post")
	- cat_url: filter on cat_url field
	- cat_id: filter on cat_id field
	- start: start with a given category
	- level: categories level to retrieve

	@param	params	<b>array</b>		Parameters
	@return	<b>record</b>
	*/
	public function getCategories($params=array())
	{

Donc, sur l'appel de getCategories() on peux   déjà préciser quelques paramètres pour filtrer le résultat de la requête. C'est peut-être par là qu'il faut commencer?


Photo, Art et Création Numérique : http://benoit-grelier.photo7.fr/

Hors ligne

#37 2016-05-19 19:20:33

Welsh
Membre
Inscription : 2011-12-28

Re : [plugin mrvbCustomWidgets] support et discussion

Si je comprends bien, on pourrait garder le code de Mirovinbien en :
- testant si le paramètre de niveau est renseigné pour le passer  à getCategories
- ne se préoccupant plus de savoir dans le traitement du resultset si le niveau de l'enregistrement traité correspond ou pas.

C'est ça ?

Hors ligne

#38 2016-05-19 20:03:13

adjaya
Membre
Lieu : Provence - Luberon
Inscription : 2006-09-05
Site Web

Re : [plugin mrvbCustomWidgets] support et discussion

Dit autrement, aller faire ses emplettes avec une liste des choses utiles, éviter de ramener tout l'étalage, ca fera moins de choses inutiles à trier et moins cher question utilisation des ressource :)


Photo, Art et Création Numérique : http://benoit-grelier.photo7.fr/

Hors ligne

#39 2016-05-19 20:24:15

Welsh
Membre
Inscription : 2011-12-28

Re : [plugin mrvbCustomWidgets] support et discussion

Tout à fait !

J'ai testé en direct-live.
Dans _public.php, j'ai enlevé le test avec max_level.
D'autre part, j'ai remplacé l'appel à getCategories() par

$rs = $core->blog->getCategories(array('level'=>2));

Ca marche pô ! Ca me donne un niveau, le second.

Edit : normal, quand on lit la doc

categories level to retrieve

. Ca veut bien dire récupérer les catégories du niveau qu'on donne et pas la profondeur des catégories. Donc uniquement le niveau 2 (dans mon cas) et pas du niveau 1 au niveau 2.

Il faudrait peut être dans ce cas là :
- faire un getCategories sans filtre
- boucler sur le resultset pour enlever celle de niveau ne convenant pas
- traiter sans la condition sur le maxlevel.

Dernière modification par Welsh (2016-05-19 20:29:17)

Hors ligne

#40 2016-05-19 20:35:50

Welsh
Membre
Inscription : 2011-12-28

Re : [plugin mrvbCustomWidgets] support et discussion

Je l'ai !

Dans le fetch, après la condition d'exclusion sur l'identifiant, j'ai jouté le test sur le niveau et j'ai enlevé le test par rapport à max_level plus loin.

A tester bien sûr !

Evidemment ce n'est pas très propre, il peut y avoir plus élégant. Si cela tente quelqu'un...

Le code est désormais :

        public static function mrvb_SubCategories($w)
        {
                global $core, $_ctx;
                if ($w->offline) {
                        return;
                }
                if (($w->homeonly == 1 && $core->url->type != 'default') ||
                        ($w->homeonly == 2 && $core->url->type == 'default')) {
                        return;
                }
                $rs = $core->blog->getCategories();
                if ($rs->isEmpty()) {
                        return;
                }
                $exclude = mrvb_ListToArray($w->excludeID);
                $res = ($w->content_only ? '' : '<div class="categories mrvbsubcategories'.($w->CSSclass ? ' '.html::escapeHTML($w->CSSclass) : '').'">');
                if (version_compare(DC_VERSION,'2.7','>=')) {
                        $res .= ($w->title ? $w->renderTitle(html::escapeHTML($w->title)) : '');
                } else {
                        $res .= ($w->title ? '<h2>'.html::escapeHTML(__($w->title)).'</h2>' : '');
                }
                $max_level = abs((integer) $w->maxlevel);
                $ref_level = $level = $rs->level-1;
                $cat_level = 0;
                while ($rs->fetch()) {
                        if (!(in_array($rs->cat_id, $exclude))){
                        if ($rs->level <= $max_level ) {
                                ($w->countsubcat ? $postcount = $rs->nb_total : $postcount = $rs->nb_post);
                                $class = ' class="cat'.$rs->cat_id;
                                if (($core->url->type == 'category' && $_ctx->categories instanceof record && $_ctx->categories->cat_id == $rs->cat_id)
                                || ($core->url->type == 'post' && $_ctx->posts instanceof record && $_ctx->posts->cat_id == $rs->cat_id)) {
                                        $class .= ' category-current';
                                }
                                $class .= '"';
                                if ($rs->level > $level) {
                                        $cat_level += 1;
                                        $res .= str_repeat('<ul><li'.$class.'>',$rs->level - $level);
                                } elseif ($rs->level < $level) {
                                        $cat_level -= 1;
                                        $res .= str_repeat('</li></ul>',-($rs->level - $level));
                                }
                                // if (($max_level == 0) || ($cat_level < $max_level + 1)){
                                        if ($rs->level <= $level) {
                                                $res .= '</li><li'.$class.'>';
                                        }
                                        $res .= '<a href="'.$core->blog->url.$core->url->getBase('category').'/'.$rs->cat_url.'"';
                                        if ($w->showcount == 'showballoon'){
                                                $res .= ' title="'.$postcount.'"';
                                        }
                                        $res .= '>'.html::escapeHTML(__($rs->cat_title)).'</a>';
                                        if ($w->showcount == 'showafter'){
                                                $res .= ' ('.$postcount.')';
                                        }
                                // }
                                $level = $rs->level;
                        }
                        }
                }
                  if ($ref_level - $level < 0) {
                        $res .= str_repeat('</li></ul>',-($ref_level - $level));
                }
                $res .= ($w->content_only ? '' : '</div>');
                return $res;
        }

Dernière modification par Welsh (2016-05-19 20:44:11)

Hors ligne

#41 2016-05-19 20:46:26

Welsh
Membre
Inscription : 2011-12-28

Re : [plugin mrvbCustomWidgets] support et discussion

Bon pas très propre car le cas où max_level vaut 0 ou n'est pas renseigné n'est pas géré.
Mais le principe est là.

Hors ligne

#42 2016-05-19 22:19:39

adjaya
Membre
Lieu : Provence - Luberon
Inscription : 2006-09-05
Site Web

Re : [plugin mrvbCustomWidgets] support et discussion

zut, presque... bon, ce coup là m’intéresse (égoïstement parlant) car j'ai un projet qui doit traiter ce type de requête sur getCategories().
Pour moi, le magasin c'est la base de donnée, si on remonte à la source je tombe sur
    public function getChildren($start=0,$id=null,$sort='asc',$fields=array()) de abstract class nestedTree
Dans le constructeur  de la classe étendue (class dcCategories extends nestedTree  ) il y a un
$this->add_condition = array('blog_id' => "'".$this->con->escape($this->blog_id)."'"); qui m’intéresse.
C'est un peu bridé mais j'ai envie de faire des test à ce niveau.
Bon je continue mon idée et reviens ici si je trouve QQ chose à proposer...


Photo, Art et Création Numérique : http://benoit-grelier.photo7.fr/

Hors ligne

#43 2016-05-20 04:49:11

Mirovinben
M comme Mathusalem
Lieu : Dole (Jura)
Inscription : 2007-02-06
Site Web

Re : [plugin mrvbCustomWidgets] support et discussion

Je vous remercie de vous pencher sur ce script. J'avoue avoir beaucoup de mal avec cette gestion des sous-catégories associé à la mise en place ici des <ul><li><ul><li></li></ul></li></ul> imbriqués.

Jusqu'à présent, mon plugin était compatible avec toutes les versions de Dotclear depuis la 2.1. Une fois la solution trouvée, en sera-t-il toujours de même ?

Hors ligne

#44 2016-05-20 06:10:19

Welsh
Membre
Inscription : 2011-12-28

Re : [plugin mrvbCustomWidgets] support et discussion

Je pense que cela devrait continuer à fonctionner. Il ne s'agit "que" d'un problème de logique. La difficulté pourrait venir de modifications sur la fonction getCategories().

Sinon, sur le problème des sous-catégories, je pense qu'une autre approche consiste à utiliser getCategories() en récursif.
On part de getCategories avec un level=>0, on a les racines.
On boucle et pour chaque on part en récursif, en ajoutant les filtres (exclusion, ...).
Un parcours d'arbre classique.

Hors ligne

#45 2016-05-20 06:26:24

Philippe
Stagiaire
Lieu : Toulon
Inscription : 2004-06-13
Site Web

Re : [plugin mrvbCustomWidgets] support et discussion

Ne peut-on pas plus simplement copier la fonction du widget natif de Dotclear et y ajouter les conditions et améliorations apportées par Mirovinben?

Hors ligne

#46 2016-05-20 06:32:07

adjaya
Membre
Lieu : Provence - Luberon
Inscription : 2006-09-05
Site Web

Re : [plugin mrvbCustomWidgets] support et discussion

@ Welsh : je reviens sur cette histoire de récursivité, les catégories sont basées sur le "Nested Sets model" qui précisément a été conçu pour éviter  d'utiliser la récursivité qui coûte cher. Ca serait perdre tout le bénéfice du concept.


Photo, Art et Création Numérique : http://benoit-grelier.photo7.fr/

Hors ligne

#47 2016-05-20 06:39:39

Welsh
Membre
Inscription : 2011-12-28

Re : [plugin mrvbCustomWidgets] support et discussion

@ adjaya : je te crois sans problème, je n'ai pas mis ta tenue de spéléologue pour aller dans les entrailles du code, comme toi. Mon propos était plus sur la "beauté" de l'algorithme. Sur le fond (performance de la récursivité), je partage ton avis.

@ Philippe : ce serait effectivement une bonne idée, mais là je crois que je vais atteindre mes limites en php...

Hors ligne

#48 2016-05-20 15:23:21

Franck
Footer de merde
Lieu : Paris
Inscription : 2004-11-09
Site Web

Re : [plugin mrvbCustomWidgets] support et discussion

adjaya a écrit :

zut, presque... bon, ce coup là m’intéresse (égoïstement parlant) car j'ai un projet qui doit traiter ce type de requête sur getCategories().
Pour moi, le magasin c'est la base de donnée, si on remonte à la source je tombe sur
    public function getChildren($start=0,$id=null,$sort='asc',$fields=array()) de abstract class nestedTree
Dans le constructeur  de la classe étendue (class dcCategories extends nestedTree  ) il y a un
$this->add_condition = array('blog_id' => "'".$this->con->escape($this->blog_id)."'"); qui m’intéresse.
C'est un peu bridé mais j'ai envie de faire des test à ce niveau.
Bon je continue mon idée et reviens ici si je trouve QQ chose à proposer...

S'il faut "débrider" des trucs, dites toujours, plutôt côté ticket, ça peut être cool de développer ça pour une des prochaines versions ;-)


Dotclear addicted since 2004

En ligne

#49 2016-05-21 08:32:10

adjaya
Membre
Lieu : Provence - Luberon
Inscription : 2006-09-05
Site Web

Re : [plugin mrvbCustomWidgets] support et discussion

@ Frank : cool, coté ticket c'est noté quand j'aurais fait de mon coté quelques tests, merci pour ta réactivité.


Photo, Art et Création Numérique : http://benoit-grelier.photo7.fr/

Hors ligne

#50 2016-05-23 07:55:32

Mirovinben
M comme Mathusalem
Lieu : Dole (Jura)
Inscription : 2007-02-06
Site Web

Re : [plugin mrvbCustomWidgets] support et discussion

Welsh a écrit :

Bon pas très propre car le cas où max_level vaut 0 ou n'est pas renseigné n'est pas géré.
Mais le principe est là.

Sur le métier j'ai remis mon ouvrage. Ou, plus exactement, je suis parti de la proposition de Welsh en #40 pour prendre en compte le cas où le champ max_level vaut 0 ou n'est pas renseigné. Partant du fait qu'avec la ligne

$max_level = abs((integer) $w->maxlevel);

si le champ n'est pas renseigné alors $max_level = 0, je propose donc d'ajouter juste en dessous ceci :

if ($max_level == 0) {
	$max_level = 65535;
}

la fonction devient donc :

public static function mrvb_SubCategories($w)
{
	global $core, $_ctx;
	if ($w->offline) {
		return;
	}
	if (($w->homeonly == 1 && $core->url->type != 'default') ||
		($w->homeonly == 2 && $core->url->type == 'default')) {
		return;
	}
	$rs = $core->blog->getCategories();
	if ($rs->isEmpty()) {
		return;
	}
	$exclude = mrvb_ListToArray($w->excludeID);
	$res = ($w->content_only ? '' : '<div class="categories mrvbsubcategories'.($w->CSSclass ? ' '.html::escapeHTML($w->CSSclass) : '').'">');
	if (version_compare(DC_VERSION,'2.7','>=')) {
		$res .= ($w->title ? $w->renderTitle(html::escapeHTML($w->title)) : '');
	} else {
		$res .= ($w->title ? '<h2>'.html::escapeHTML(__($w->title)).'</h2>' : '');
	}
	$max_level = abs((integer) $w->maxlevel);
	if ($max_level == 0) {
		$max_level = 65535;
	}
	$ref_level = $level = $rs->level-1;
	$cat_level = 0;
	while ($rs->fetch()) {
		if (!(in_array($rs->cat_id, $exclude))){
			if ($rs->level <= $max_level ) {
				($w->countsubcat ? $postcount = $rs->nb_total : $postcount = $rs->nb_post);
				$class = ' class="cat'.$rs->cat_id;
				if (($core->url->type == 'category' && $_ctx->categories instanceof record && $_ctx->categories->cat_id == $rs->cat_id)
				|| ($core->url->type == 'post' && $_ctx->posts instanceof record && $_ctx->posts->cat_id == $rs->cat_id)) {
						$class .= ' category-current';
				}
				$class .= '"';
				if ($rs->level > $level) {
						$cat_level += 1;
						$res .= str_repeat('<ul><li'.$class.'>',$rs->level - $level);
				} elseif ($rs->level < $level) {
						$cat_level -= 1;
						$res .= str_repeat('</li></ul>',-($rs->level - $level));
				}
				if ($rs->level <= $level) {
						$res .= '</li><li'.$class.'>';
				}
				$res .= '<a href="'.$core->blog->url.$core->url->getBase('category').'/'.$rs->cat_url.'"';
				if ($w->showcount == 'showballoon'){
						$res .= ' title="'.$postcount.'"';
				}
				$res .= '>'.html::escapeHTML(__($rs->cat_title)).'</a>';
				if ($w->showcount == 'showafter'){
						$res .= ' ('.$postcount.')';
				}
				$level = $rs->level;
			}
		}
	}
	if ($ref_level - $level < 0) {
		$res .= str_repeat('</li></ul>',-($ref_level - $level));
	}
	$res .= ($w->content_only ? '' : '</div>');
	return $res;
}

Ça fait méthode "gros bœuf" mais ça fonctionne pour peu qu'il n'y ait pas plus de 65535 niveaux dans l'arborescence des catégories !...

Z'en pensez quoi ?

Hors ligne

Vous n'êtes pas identifié(e).

Pied de page des forums

Sites map