Пример #1
0
 /**
  * Add a new term to the database.
  *
  * A non-existent term is inserted in the following sequence:
  *
  * 1. The term is added to the term table, then related to the taxonomy.
  * 2. If everything is correct, several actions are fired.
  * 3. The 'term_id_filter' is evaluated.
  * 4. The term cache is cleaned.
  * 5. Several more actions are fired.
  * 6. An array is returned containing the term_id and term_taxonomy_id.
  *
  * If the 'slug' argument is not empty, then it is checked to see if the term
  * is invalid. If it is not a valid, existing term, it is added and the term_id
  * is given.
  *
  * If the taxonomy is hierarchical, and the 'parent' argument is not empty,
  * the term is inserted and the term_id will be given.
  * Error handling:
  * If $taxonomy does not exist or $term is empty,
  * a WP_Error object will be returned.
  *
  * If the term already exists on the same hierarchical level,
  * or the term slug and name are not unique, a WP_Error object will be returned.
  *
  * NOTE: This is the Connections equivalent of @see wp_insert_term() in WordPress core ../wp-includes/taxonomy.php
  *
  * Actions:
  *    cn_edit_terms
  *        Passes: (int) $term_id, (string) $taxonomy
  *
  *    cn_edited_terms
  *        Passes: (int) $term_id, (string) $taxonomy
  *
  *    cn_create_term
  *        Passes: (int) $term_id, (int) $taxonomy_term_id, (string) $taxonomy
  *
  *    cn_create_$taxonomy
  *        Passes: (int) $term_id, (int) $taxonomy_term_id
  *
  *    cn_created_term
  *        Passes: (int) $term_id, (int) $taxonomy_term_id, (string) $taxonomy
  *
  *    cn_created_$taxonomy
  *       Passes: (int) $term_id, (int) $taxonomy_term_id
  *
  * Filters:
  *    cn_pre_insert_term
  *        Passes: (string) $term, (string) $taxonomy
  *        Return: $term
  *
  *    cn_term_id_filter
  *        Passes: (int) $term_id, (int) $taxonomy_term_id
  *        Return: $term_id
  *
  * @global wpdb  $wpdb            The WordPress database object.
  *
  * @access public
  * @since  8.1.6
  * @static
  *
  * @param string        $term            The term to add or update.
  * @param string        $taxonomy        The taxonomy to which to add the term
  * @param array|object  $args            {
  *    Optional. Arguments to change values of the inserted term.
  *
  *    @type string 'alias_of'        Slug of the term to make this term an alias of.
  *                                   Default: empty string.
  *                                   Accepts a term slug.
  *    @type string 'description'     The term description.
  *                                   Default: empty string.
  *    @type int    'parent'          The id of the parent term.
  *                                   Default: 0.
  *    @type string 'slug'            The term slug to use.
  *                                   Default: empty string.
  * }
  *
  * @return array|WP_Error         An array containing the term_id and term_taxonomy_id, WP_Error otherwise.
  */
 public static function insert($term, $taxonomy, $args = array())
 {
     /** @var $wpdb wpdb */
     global $wpdb;
     // @todo Implement taxonomy check.
     //if ( ! taxonomy_exists($taxonomy) ) {
     //	return new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
     //}
     /**
      * Filter a term before it is sanitized and inserted into the database.
      *
      * @since 8.1.6
      *
      * @param string $term     The term to add or update.
      * @param string $taxonomy Taxonomy slug.
      */
     $term = apply_filters('cn_pre_insert_term', $term, $taxonomy);
     if (is_wp_error($term)) {
         return $term;
     }
     if (is_int($term) && 0 == $term) {
         return new WP_Error('invalid_term_id', __('Invalid term ID', 'connections'));
     }
     if ('' == trim($term)) {
         return new WP_Error('empty_term_name', __('A name is required for this term', 'connections'));
     }
     $defaults = array('alias_of' => '', 'description' => '', 'parent' => 0, 'slug' => '');
     $args = wp_parse_args($args, $defaults);
     if (0 < $args['parent'] && !self::exists((int) $args['parent'])) {
         return new WP_Error('missing_parent', __('Parent term does not exist.', 'connections'));
     }
     $args['name'] = $term;
     $args['taxonomy'] = $taxonomy;
     $args = sanitize_term($args, 'cn_' . $taxonomy, 'db');
     // expected_slashed ($name)
     $name = wp_unslash($args['name']);
     $description = wp_unslash($args['description']);
     $parent = (int) $args['parent'];
     $slug_provided = !empty($args['slug']);
     if (!$slug_provided) {
         $slug = sanitize_title($name);
     } else {
         $slug = $args['slug'];
     }
     $term_group = 0;
     if ($args['alias_of']) {
         $alias = cnTerm::getBy('slug', $args['alias_of'], $taxonomy);
         if (!empty($alias->term_group)) {
             // The alias we want is already in a group, so let's use that one.
             $term_group = $alias->term_group;
         } elseif (!empty($alias->term_id)) {
             /*
              * The alias is not in a group, so we create a new one and add the alias to it.
              */
             $term_group = $wpdb->get_var("SELECT MAX(term_group) FROM {$wpdb->terms}") + 1;
             cnTerm::update($alias->term_id, $taxonomy, array('term_group' => $term_group));
         }
     }
     /*
      * Prevent the creation of terms with duplicate names at the same level of a taxonomy hierarchy,
      * unless a unique slug has been explicitly provided.
      */
     $name_matches = self::getTaxonomyTerms($taxonomy, array('name' => $name, 'hide_empty' => false));
     /*
      * The `name` match in `self::getTaxonomyTerms()` doesn't differentiate accented characters,
      * so we do a stricter comparison here.
      */
     $name_match = NULL;
     if ($name_matches) {
         foreach ($name_matches as $_match) {
             if (strtolower($name) === strtolower($_match->name)) {
                 /** @var cnTerm_Object $name_match */
                 $name_match = $_match;
                 break;
             }
         }
     }
     if ($name_match) {
         $slug_match = cnTerm::getBy('slug', $slug, $taxonomy);
         if (!$slug_provided || $name_match->slug === $slug || $slug_match) {
             if (is_taxonomy_hierarchical($taxonomy)) {
                 $siblings = self::getTaxonomyTerms($taxonomy, array('get' => 'all', 'parent' => $parent));
                 $existing_term = NULL;
                 if ($name_match->slug === $slug && in_array($name, wp_list_pluck($siblings, 'name'))) {
                     $existing_term = $name_match;
                 } elseif ($slug_match && in_array($slug, wp_list_pluck($siblings, 'slug'))) {
                     $existing_term = $slug_match;
                 }
                 if ($existing_term) {
                     return new WP_Error('term_exists', __('A term with the name provided already exists with this parent.', 'connections'), $existing_term->term_id);
                 }
             } else {
                 return new WP_Error('term_exists', __('A term with the name provided already exists in this taxonomy.', 'connections'), $name_match->term_id);
             }
         }
     }
     $slug = cnTerm::unique_slug($slug, (object) $args);
     if (FALSE === $wpdb->insert(CN_TERMS_TABLE, compact('name', 'slug', 'term_group'))) {
         return new WP_Error('db_insert_error', __('Could not insert term into the database', 'connections'), $wpdb->last_error);
     }
     $term_id = (int) $wpdb->insert_id;
     // Seems unreachable, However, Is used in the case that a term name is provided, which sanitizes to an empty string.
     if (empty($slug)) {
         $slug = sanitize_title($slug, $term_id);
         /** @see cnTerm::insert() */
         do_action('cn_edit_terms', $term_id, $taxonomy);
         $wpdb->update(CN_TERMS_TABLE, compact('slug'), compact('term_id'));
         /** @see cnTerm::insert() */
         do_action('cn_edited_terms', $term_id, $taxonomy);
     }
     $tt_id = $wpdb->get_var($wpdb->prepare("SELECT tt.term_taxonomy_id FROM " . CN_TERM_TAXONOMY_TABLE . " AS tt INNER JOIN " . CN_TERMS_TABLE . " AS t ON tt.term_id = t.term_id WHERE tt.taxonomy = %s AND t.term_id = %d", $taxonomy, $term_id));
     if (!empty($tt_id)) {
         return array('term_id' => $term_id, 'term_taxonomy_id' => $tt_id);
     }
     $wpdb->insert(CN_TERM_TAXONOMY_TABLE, compact('term_id', 'taxonomy', 'description', 'parent') + array('count' => 0));
     $tt_id = (int) $wpdb->insert_id;
     /*
      * Sanity check: if we just created a term with the same parent + taxonomy + slug but a higher term_id than
      * an existing term, then we have unwittingly created a duplicate term. Delete the dupe, and use the term_id
      * and term_taxonomy_id of the older term instead. Then return out of the function so that the "create" hooks
      * are not fired.
      */
     $duplicate_term = $wpdb->get_row($wpdb->prepare("SELECT t.term_id, tt.term_taxonomy_id FROM " . CN_TERMS_TABLE . " t INNER JOIN " . CN_TERM_TAXONOMY_TABLE . " tt ON ( tt.term_id = t.term_id ) WHERE t.slug = %s AND tt.parent = %d AND tt.taxonomy = %s AND t.term_id < %d AND tt.term_taxonomy_id != %d", $slug, $parent, $taxonomy, $term_id, $tt_id));
     if ($duplicate_term) {
         $wpdb->delete($wpdb->terms, array('term_id' => $term_id));
         $wpdb->delete($wpdb->term_taxonomy, array('term_taxonomy_id' => $tt_id));
         $term_id = (int) $duplicate_term->term_id;
         $tt_id = (int) $duplicate_term->term_taxonomy_id;
         cnTerm::cleanCache($term_id, $taxonomy);
         return array('term_id' => $term_id, 'term_taxonomy_id' => $tt_id);
     }
     /**
      * Fires immediately after a new term is created, before the term cache is cleaned.
      *
      * @since 8.1.6
      *
      * @param int    $term_id  Term ID.
      * @param int    $tt_id    Term taxonomy ID.
      * @param string $taxonomy Taxonomy slug.
      */
     do_action("cn_create_term", $term_id, $tt_id, $taxonomy);
     /**
      * Fires after a new term is created for a specific taxonomy.
      *
      * The dynamic portion of the hook name, $taxonomy, refers
      * to the slug of the taxonomy the term was created for.
      *
      * @since 8.1.6
      *
      * @param int $term_id Term ID.
      * @param int $tt_id   Term taxonomy ID.
      */
     do_action("cn_create_{$taxonomy}", $term_id, $tt_id);
     /**
      * Filter the term ID after a new term is created.
      *
      * @since 8.1.6
      *
      * @param int $term_id Term ID.
      * @param int $tt_id   Taxonomy term ID.
      */
     $term_id = apply_filters('cn_term_id_filter', $term_id, $tt_id);
     self::cleanCache($term_id, $taxonomy);
     /**
      * Fires after a new term is created, and after the term cache has been cleaned.
      *
      * @since 8.1.6
      */
     do_action("cn_created_term", $term_id, $tt_id, $taxonomy);
     /**
      * Fires after a new term in a specific taxonomy is created, and after the term
      * cache has been cleaned.
      *
      * @since 8.1.6
      *
      * @param int $term_id Term ID.
      * @param int $tt_id   Term taxonomy ID.
      */
     do_action("cn_created_{$taxonomy}", $term_id, $tt_id);
     return array('term_id' => $term_id, 'term_taxonomy_id' => $tt_id);
 }