Vorsicht beim Setzen von Terms mit wp set object terms()

Um gleich mit der Tür in’s Haus zu fallen:

Warum?

Weil nicht überprüft wird, ob die Taxonomy des Terms mit dem Objekt verknüpft ist.
Es wird zB nicht überprüft, ob eine Kategorie der eingebauten Taxonomy ‚category‘ mit dem Beitragposttype ‚Post‘ verbunden ist.
Ob es daher überhaupt erlaubt ist, zB einem Beitrag eine Kategorie zuzuweisen.

Trotzdem wird das Term zum Objekt gespeichert!!

Ok, das Beispiel ist recht sinnlos weil wir ja wissen, dass Beiträge ganz einfach in Kategorien eingereiht werden können. Das Beispiel dient nur der Veranschaulichung.

Viel interessanter wird es beim Zuweisen von Custom Taxonomy Terms, also den selbst erstellten „Tags“ und „Kategorien“.

wp_set_object_terms() überprüft nämlich nicht, ob der Beitrag den ich gerade „tagge“ auch wirklich mit der Custom Taxonomy verbunden ist.
Genau das wird problematisch, wenn man  Geschäftslogik mit eigenen Kategorien oder Tags löst.
Denn ich kann mit wp_set_object_terms() zB eine Seite ohne Probleme (und ohne Fehlermeldung) out-of-the-box einen Tag oder eine Kategorie zuweisen.

Lösung:

Vor dem Speichern mit wp set object terms() einfach überprüfen, ob der „Post“ (also das Objekt) eh mit der entsprechenden Custom Taxonomy verknüpft ist.

Wie finde ich das heraus?

Lösung mit der globalen wp_taxonomies Variable:

  global $wp_taxonomies;
  $alle_taxonomie_objekte   = $wp_taxonomies;
  $zugewiesenen_taxonomien  = $alle_taxonomie_objekte['category']->object_type;
  /*
  Array
  (
      [0] => post
      [1] => my_custom_post_type_wpent
  )
  */

Es gibt eine globale Variable, die alle Taxonomien mit den diversen Informationen bereithält. Wir sehen in diesem Beispiel, dass die normale WordPress Kategorie mit den Beiträgen (‚posts‘) und einem Custom Post Type (‚my_custom_post_type_wpent‘) verknüpft ist.
Aber eben nicht mit dem ‚Page‘ Post Type aka „Seiten“.

Lösung mit get_object_taxonomies()

Den oben beschriebenen Weg können wir abkürzen, wenn wir die Funktion get_object_taxonomies() verwenden. Damit wird genau das oben gezeigte Array geholt. Im WP Codex gibt es dafür ein schönes Beispiel:

   $taxonomy_names = get_object_taxonomies( 'post' );
   print_r( $taxonomy_names);

Gibt uns folgendes zurück:

Array
(
    [0] => category
    [1] => post_tag
    [2] => post_format
)

 

Alternativ mit wp_get_object_terms()

Man könnte auch direkt mit wp_get_object_terms() alle Terms abfragen, die zu einem Post gehören.

 wp_get_object_terms( 123, 'my_custom_taxonomy_wpent' );

Ist die Taxonomy (hier „my_custom_taxonomy_wpent“) nicht mit dem Post 123 verknüpft, wird ein wp_error zurückgegeben.
Als Fehlermeldung bekommt man den Hinweis  „invalid_taxonomy“ zurück und kann darauf reagieren.

 Wie kommt es dazu?

Die Funktion wp_set_object_terms() ist in der Datei „taxonomy.php“ enthalten.

Es wird überprüft ob der übergebene Term existiert:
https://github.com/WordPress/WordPress/blob/4.1-branch/wp-includes/taxonomy.php#L2991

if ( !$term_info = term_exists($term, $taxonomy) ) {

 

Schauen wir uns die Funktion weiter näher an so sehen wir, dass zweimal die Funktion wp_get_object_terms() aufgerufen wird.
Diese Funktion liefert in unserem Fall ja einen Fehler zurück. Doch leider zu spät, da das Term schon gespeichert wurde. Außerdem wird gar nicht auf wp_error überprüft.

https://github.com/WordPress/WordPress/blob/4.1-branch/wp-includes/taxonomy.php#L2979

https://github.com/WordPress/WordPress/blob/4.1-branch/wp-includes/taxonomy.php#L3051

In beiden Fällen bekommt jetzt eine Variable ein wp_error Objekt zugewiesen. Keine der Variablen wird auf diesen Umstand hin überprüft.

 

Die Speicherung eines Terms, der eigentlich gar nicht mit einem Objekt (Post, Page, CPT) über die Taxonomy verknüpft ist, geht problemlos über die Bühne.

 

Informatives:

Check ob Term besteht
http://codex.wordpress.org/Function_Reference/term_exists

http://codex.wordpress.org/Function_Reference/term_exists

 

Check ob es die Taxonomy gibt
https://codex.wordpress.org/Function_Reference/taxonomy_exists
https://codex.wordpress.org/Function_Reference/taxonomy_exists

 

Holt alle Taxonomien eines Posts (Objektes)
http://codex.wordpress.org/Function_Reference/get_object_taxonomies
http://codex.wordpress.org/Function_Reference/get_object_taxonomies

 

wp_set_object_terms() auf Github
https://github.com/WordPress/WordPress/blob/4.1-branch/wp-includes/taxonomy.php#L2950
https://github.com/WordPress/WordPress/blob/4.1-branch/wp-includes/taxonomy.php#L2950

 

wp_get_object_terms() im Codex
http://codex.wordpress.org/Function_Reference/wp_get_object_terms
http://codex.wordpress.org/Function_Reference/wp_get_object_terms

 

wp_set_object_terms() im Codex
https://codex.wordpress.org/Function_Reference/wp_set_object_terms
https://codex.wordpress.org/Function_Reference/wp_set_object_terms

 

Check ob der Post einen gewissen Term hat
http://codex.wordpress.org/Function_Reference/has_term
http://codex.wordpress.org/Function_Reference/has_term

 

 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.