UND Verknüpfung in der Kategoriensicht

Hier können Probleme und alles andere in Deutscher Sprache gelöst werden.
soylentgreen
Regular
Posts: 28
Joined: Sun Aug 20, 2006 2:54 pm

UND Verknüpfung in der Kategoriensicht

Post by soylentgreen »

Hallo,

gibt es eine Möglichkeit nur Beiträge anzuzeigen, die zu zwei Kategorien gehören?

In dem Kategorie-Plugin gibt es eine Möglichkeit mehrere auszuwählen, allerdings sind dann alle Beiträge dieser beiden Kategorien vorhanden (ODER verknüpft). Ich benötige jedoch eine UND Verknüpfung...

Daher meine Frage:
gibt es eine einfache Möglichkeit (ein Plugin oder einen Patch), der es ermöglicht, Beiträge anhand UND verknüpfter Kategorien zu filtern?

Vielen Dank im vorraus!
garvinhicking
Core Developer
Posts: 30022
Joined: Tue Sep 16, 2003 9:45 pm
Location: Cologne, Germany
Contact:

Re: UND Verknüpfung in der Kategoriensicht

Post by garvinhicking »

Hi!

Wo genau möchtest Du diese Anzeige forcieren? Ich verstehe noch nicht so ganz, wo/wie man sowas einbinden sollte. Gehen tut das natürlich, man muss nur ein plugin mit frontend_fetchentries hook schreiben und den SQL-Code modifizieren.

Grüße,
Garvin
# Garvin Hicking (s9y Developer)
# Did I help you? Consider making me happy: http://wishes.garv.in/
# or use my PayPal account "paypal {at} supergarv (dot) de"
# My "other" hobby: http://flickr.garv.in/
soylentgreen
Regular
Posts: 28
Joined: Sun Aug 20, 2006 2:54 pm

Post by soylentgreen »

hi!

was meinst du mit wo? ich dachte an das sidebar kategorie plugin. ich bräuchte dieses, da ich immer einträge mit mehr als einer kategorie habe und diese auch gezielt filtern möchte.

ich habe allerdings keine ahnung, wie ich am einfachsten so ein plugin erstelle, daher wäre ein grober hinweis in die richtige richtung sehr hilfreich
garvinhicking
Core Developer
Posts: 30022
Joined: Tue Sep 16, 2003 9:45 pm
Location: Cologne, Germany
Contact:

Post by garvinhicking »

Hi!

Dir geht es um die Anzahl der Einträge, die im Kategorien-Seitenleisten-Plugin angezeigt werden?

Oder geht es Dir um die Seite, die folgt, wenn Du auf eine Kategorie in der Seitenleiste klickst? Und woher weiß die Folgeseite dann, welche zweite Kategorie für Dich als Auswahl galt? Willst Du die Kategorien hart im Code verdrahten?

Du müsstest es leider genau beschreiben, damit ich helfen kann. :)

Viele Grüße,
Garvin
# Garvin Hicking (s9y Developer)
# Did I help you? Consider making me happy: http://wishes.garv.in/
# or use my PayPal account "paypal {at} supergarv (dot) de"
# My "other" hobby: http://flickr.garv.in/
soylentgreen
Regular
Posts: 28
Joined: Sun Aug 20, 2006 2:54 pm

Post by soylentgreen »

Hallo nochmal

Also die Einträge, wie sie im Sidebar-Plugin angezeigt werden sind ok sie wie sie sind.. es gibt ja die Möglichkeit, dort auch mehrere anzuklicken (mit Radio-Checkboxen) und diese dann in einer Liste anzuzeigen. Wenn man mehrere anklickt werden diese jedoch ODER verknüpft, d.h.
wenn ich Kategorie a und b und c hab, und ich a und b wähle, werden alle angezeigt, die in a ODER b sind.

Ich würde dagegen gerne haben, dass nur diejenigen anzeigt werden, die in A UND B sind, also eine restriktivere Suche. Das müsste ja durch das austauschen eines SQL Schlüsselwortes schon machbar sein, allerdings weiss ich nicht genau wo ich den Hebel da ansetzen muss, da der Quellcode doch recht umfangreich ist. Am besten wäre es natürlich, wenn man im Plugin wählen könnte, ob die Einträge UND oder ODER verknüpft sind, mir persönlich würde aber in diesem Fall eine UND Verknüpfung reichen

ich hoffe ich habe mich jetzt etwas deutlicher ausgedrückt ;)

Viele Grüße
Stefan
garvinhicking
Core Developer
Posts: 30022
Joined: Tue Sep 16, 2003 9:45 pm
Location: Cologne, Germany
Contact:

Post by garvinhicking »

Hi!

Okay, dann editier mal deine include/functions_entries.inc.php und suche nach:

Code: Select all

    if (isset($serendipity['GET']['category'])) {
        $cat_sql = serendipity_getMultiCategoriesSQL($serendipity['GET']['category']);
Ersetze das durch:

Code: Select all

    if (isset($serendipity['GET']['category'])) {
        $cat_sql = serendipity_getMultiCategoriesSQL($serendipity['GET']['category'], true);
(Der zweite Parameter 'true' zur Funktion gibt an, dass eine AND-Verkettung genutzt werden soll)

Viele Grüße,
Garvin
# Garvin Hicking (s9y Developer)
# Did I help you? Consider making me happy: http://wishes.garv.in/
# or use my PayPal account "paypal {at} supergarv (dot) de"
# My "other" hobby: http://flickr.garv.in/
soylentgreen
Regular
Posts: 28
Joined: Sun Aug 20, 2006 2:54 pm

Post by soylentgreen »

Hallo Garvin,

die von dir vorgeschlagene Stelle kommt in zwei Funktionen vor (fetch_entries (ich denke das ist die richtige stelle) und print_archives)

Allerdings scheint die Änderung ein paar Dinge durcheinander zu werfen... ein Klick auf eine einzelne Kategorie zeigt alle Einträge an (auch von Kategorie, zu denen keine Einträge erstellt wurden), wenn ich die Kombination aus zwei Kategorien verwende, werden alle anderen, nur nicht die richtigen, anzeigt; eine inversive Menge quasi ;)

Wird die Methode getMultiCategoriesSQL noch anderswo verwendet und können Seiteneffekte auftreten, wenn ich da jetzt selbst hand anlege?

Gruß
Stefan
soylentgreen
Regular
Posts: 28
Joined: Sun Aug 20, 2006 2:54 pm

Post by soylentgreen »

OK, ich habe(nach etwas rumprobieren ;)) die serendipity_getMultiCategoriesSQL modifiziert, allerdings glaube ich kaum, dass das die eleganteste Methode ist ;)

Die Abfrage musste für die UND verknüpfung recht stark umgebaut werden (mittels einer Subquery mit having... eine einfachere Methode fiel mir ad hoc nicht ein)

Das ganze ist eher als Hack zu sehen... gibt es da eine Möglichkeit das eleganter zu intergrieren, so dass es auch bei Updates noch zur Verfügung steht?

Bei Bedarf kann ich eine gepatchte Methode hier posten
garvinhicking
Core Developer
Posts: 30022
Joined: Tue Sep 16, 2003 9:45 pm
Location: Cologne, Germany
Contact:

Post by garvinhicking »

Hi!

Welche Serendipity-Version setzt Du ein? Wie sieht dein Patch aus?

Viele Grüße,
Garvin
# Garvin Hicking (s9y Developer)
# Did I help you? Consider making me happy: http://wishes.garv.in/
# or use my PayPal account "paypal {at} supergarv (dot) de"
# My "other" hobby: http://flickr.garv.in/
soylentgreen
Regular
Posts: 28
Joined: Sun Aug 20, 2006 2:54 pm

Post by soylentgreen »

hi, ich hab die aktuelle stable (1.0.1) genutzt... der blog wird noch aufgesetzt.

der patch sieht folgendermaßen aus:

Code: Select all

/**
 * Returns SQL code to use when fetching entries that are contained within multiple categories
 *
 * @access public
 * @param  string   A listing of category ids to check, separated by ";"
 * @param  boolean  Toggle whether to include or exclude entries of this category
 * @param  boolean  Toggle wheter to include only entries from all categories (invert must be false)
 * @return string   Returns the SQL code for selecting entries of the calculated categories
 */
function serendipity_getMultiCategoriesSQL($cats, $invert = false, $special = false) {
    global $serendipity;

    $mcategories   = explode(';', $cats);
    $cat_sql_array = array();
    foreach($mcategories AS $categoryid) {
        $categoryid  = (int)$categoryid;

        if ($categoryid != 0) {
            $cat_sql_array[] = " (c.category_left " . ($invert ? " NOT " : "") . " BETWEEN " . implode(' AND ', serendipity_fetchCategoryRange($categoryid)) . ')';
        }
    }
    //Begin patch
    $result_string = '(' . implode(($invert ? ' AND ' : ' OR '), $cat_sql_array) . ')';
    if ($special)
    {


    	$new_result_string = ' (e.id in (select ec2.entryid from serendipity_entrycat ec2 left join serendipity_category c2 on ec2.categoryid = c2.categoryid where ';
    	$new_result_string = $new_result_string .   ereg_replace('c.category_left','c2.category_left',$result_string);
    	$new_result_string = $new_result_string . ' group by ec2.entryid having count(ec2.entryid) = ' . count($mcategories) . ')) ';
    	$result_string = $new_result_string;
    }
	//End patch
    return $result_string;
}
anmerkung: ich habe einen dritten Parameter eingeführt (special), damit er nicht unbeabsichtigt von anderen methoden aufgerufen wird

in fetch_entries wird das ganze dann so aufgerufen:

Code: Select all

    if (isset($serendipity['GET']['category'])) {
        $cat_sql = serendipity_getMultiCategoriesSQL($serendipity['GET']['category'], false,true);
    } 
es scheint hier zu funktionieren (mit mysql 4.1), allerdings unterstützen alte mysql versionen (4.0 bspw) keine Subqueries, so dass es nur eingeschränkt portabel ist. Ich hoffe, dass der Patch mit postgres zusammen arbeitet, das ist nämlich die spätere Produktivumgebung.
garvinhicking
Core Developer
Posts: 30022
Joined: Tue Sep 16, 2003 9:45 pm
Location: Cologne, Germany
Contact:

Post by garvinhicking »

Hi!

Dieser patch hier sollte sinnvoller sein:

Code: Select all

function serendipity_getMultiCategoriesSQL($cats, $invert = false, $combine = ' OR ') {
    global $serendipity;

    if (strtolower(trim($combine)) == 'and') {
        $combine_invert = ' OR ';
    } else {
        $combine_invert = ' AND ';
    }

    $mcategories   = explode(';', $cats);
    $cat_sql_array = array();
    foreach($mcategories AS $categoryid) {
        $categoryid  = (int)$categoryid;

        if ($categoryid != 0) {
            $cat_sql_array[] = " (c.category_left " . ($invert ? " NOT " : "") . " BETWEEN " . implode(' AND ', serendipity_fetchCategoryRange($categoryid)) . ')';
        }
    }

    return $result_string;
} 
danach kannst Du einfach $combine = ' AND ' an die Funktion übermitteln?

Grüße,
Garvin
# Garvin Hicking (s9y Developer)
# Did I help you? Consider making me happy: http://wishes.garv.in/
# or use my PayPal account "paypal {at} supergarv (dot) de"
# My "other" hobby: http://flickr.garv.in/
soylentgreen
Regular
Posts: 28
Joined: Sun Aug 20, 2006 2:54 pm

Post by soylentgreen »

Hallo nochmal,

ich habe deinen Patch ausprobiert, allerdings scheinen deutlich mehr änderungen am SQL notwendig zu sein; ein einfaches austauschen des Verknüpfungsoperators scheint nicht auszureichen. die Ursprüngliche version erzeugt den folgenden SQL block (bei zwei parametern):

Code: Select all

( (c.category_left BETWEEN 7 AND 8) OR (c.category_left BETWEEN 1 AND 2))
nach meinem Patch erscheint das folgende Fragment

Code: Select all

(e.id in 
(select ec2.entryid 
   from serendipity_entrycat ec2 
           left join serendipity_category c2 on ec2.categoryid = c2.categoryid 
where 
( (c2.category_left BETWEEN 7 AND 8) OR 
  (c2.category_left BETWEEN 1 AND 2)) 
group by ec2.entryid having count(ec2.entryid) = 2))
das problem bei der umstellung war, dass die categorie information in einem join hinzugezogen wird, und daher die bedingung niemals gleichzeitig zwei werte haben kann... mit einer ODER Verknüpfung ist das dagegen möglich. Deshalb habe ich die nicht ganz elegante variante über das Subquery mit dem count gewählt, allerdings könnte es gut sein, dass es eine elegantere methode dafür gibt, sie ist mir bisher allerdings noch nicht eingefallen
garvinhicking
Core Developer
Posts: 30022
Joined: Tue Sep 16, 2003 9:45 pm
Location: Cologne, Germany
Contact:

Post by garvinhicking »

Hi!

Ach! Jetzt sehe ich erst, was Du willst. Ja, ich fürchte das geht wohl nur mit Subselects oder mehreren Queries. Da subselects von sqlite und pgsql nur unterschiedlich interpretiert werden, können wir das so nicht in den s9y core aufnehmen...da wäre also definitiv einiges an Arbeit für korrekte Query-Formung notwendig.

In deinem Patch z.B. wird im Subselect die ganze Leserecht-Sache niht abgefragt, die müsste ja auch beinhaltet werden...

Viele Grüße,
Garvin
# Garvin Hicking (s9y Developer)
# Did I help you? Consider making me happy: http://wishes.garv.in/
# or use my PayPal account "paypal {at} supergarv (dot) de"
# My "other" hobby: http://flickr.garv.in/
soylentgreen
Regular
Posts: 28
Joined: Sun Aug 20, 2006 2:54 pm

Post by soylentgreen »

Hi,

dann bin ich mal gespannt ob das gleich unter pgsql funktioniert, sonst muss ich da nochmal hand anlegen...

ach, die leserechte sind auch an Kategorien gekoppelt... wird das auch in dieser Methode abgefragt?

In meinem konkreten Anwendungsfall ist das nicht so schlimm, da die Rechte für alle angemeldeten Benutzer gleich sein sollen. Ich habe jedoch vor, Beiträge nur für eingeloggte Benutzer sichtbar zu machen über das "erweiterte Eigenschaften"-Plugin... oder spricht durch den Patch jetzt etwas dagegen?

Gruß
Stefan
garvinhicking
Core Developer
Posts: 30022
Joined: Tue Sep 16, 2003 9:45 pm
Location: Cologne, Germany
Contact:

Post by garvinhicking »

Hi!
ach, die leserechte sind auch an Kategorien gekoppelt... wird das auch in dieser Methode abgefragt?
Nein, das passiert an anderer Stelle in der serendipity_fetchEntries() Funktion. Die getSQL Funktion behandelt nur das holen der Category-IDs, mit denen gejoined werden soll.
In meinem konkreten Anwendungsfall ist das nicht so schlimm, da die Rechte für alle angemeldeten Benutzer gleich sein sollen. Ich habe jedoch vor, Beiträge nur für eingeloggte Benutzer sichtbar zu machen über das "erweiterte Eigenschaften"-Plugin... oder spricht durch den Patch jetzt etwas dagegen?
Jau, jedoch können wir einen Patch der diese Voraussetzung ausnutzt, nicht offiziell aufnehmen. Der Patch würde dadurch evtl. Einträge anzeigen, die eigentlich in geschützten Kategorien liegen.

Viele Grüße,
Garvin
# Garvin Hicking (s9y Developer)
# Did I help you? Consider making me happy: http://wishes.garv.in/
# or use my PayPal account "paypal {at} supergarv (dot) de"
# My "other" hobby: http://flickr.garv.in/
Post Reply