/**
  * Add, update or delete the entry meta data.
  *
  * @access public
  * @since  0.8
  * @param  string $action The action to being performed to an entry.
  * @param  int    $id     The entry ID.
  *
  * @return mixed          array | bool  An array of meta IDs or FALSE on failure.
  */
 public static function processEntryMeta($action, $id)
 {
     /** @var wpdb $wpdb */
     global $wpdb;
     if (!($id = absint($id))) {
         return FALSE;
     }
     $meta = array();
     $newmeta = array();
     $metaSelect = array();
     $metaIDs = array();
     switch ($action) {
         case 'add':
             if (isset($_POST['newmeta']) || !empty($_POST['newmeta'])) {
                 foreach ($_POST['newmeta'] as $row) {
                     // If the key begins with an underscore, remove it because those are private.
                     if (isset($row['key'][0]) && '_' == $row['key'][0]) {
                         $row['key'] = substr($row['key'], 1);
                     }
                     $newmeta[] = cnMeta::add('entry', $id, $row['key'], $row['value']);
                 }
             }
             if (isset($_POST['metakeyselect']) && $_POST['metakeyselect'] !== '-1') {
                 $metaSelect[] = cnMeta::add('entry', $id, $_POST['metakeyselect'], $_POST['newmeta']['99']['value']);
             }
             $metaIDs['added'] = array_merge($newmeta, $metaSelect);
             break;
         case 'copy':
             // Copy any meta associated with the source entry to the new entry.
             if (isset($_POST['meta']) || !empty($_POST['meta'])) {
                 foreach ($_POST['meta'] as $row) {
                     // If the key begins with an underscore, remove it because those are private.
                     if (isset($row['key'][0]) && '_' == $row['key'][0]) {
                         $row['key'] = substr($row['key'], 1);
                     }
                     // Add the meta except for those that the user deleted for this entry.
                     if ($row['value'] !== '::DELETED::') {
                         $meta[] = cnMeta::add('entry', $id, $row['key'], $row['value']);
                     }
                 }
             }
             // Lastly, add any new meta the user may have added.
             if (isset($_POST['newmeta']) || !empty($_POST['newmeta'])) {
                 foreach ($_POST['newmeta'] as $row) {
                     // If the key begins with an underscore, remove it because those are private.
                     if (isset($row['key'][0]) && '_' == $row['key'][0]) {
                         $row['key'] = substr($row['key'], 1);
                     }
                     $metaIDs[] = cnMeta::add('entry', $id, $row['key'], $row['value']);
                 }
                 // $newmeta = cnMeta::add( 'entry', $id, $_POST['newmeta']['0']['key'], $_POST['newmeta']['99']['value'] );
             }
             if (isset($_POST['metakeyselect']) && $_POST['metakeyselect'] !== '-1') {
                 $metaSelect[] = cnMeta::add('entry', $id, $_POST['metakeyselect'], $_POST['newmeta']['99']['value']);
             }
             $metaIDs['added'] = array_merge($meta, $newmeta, $metaSelect);
             break;
         case 'update':
             // Query the meta associated to the entry.
             //$results = cnMeta::get( 'entry', $id );
             $results = $wpdb->get_results($wpdb->prepare("SELECT meta_key, meta_value, meta_id, entry_id\n\t\t\t\t\t\t\tFROM " . CN_ENTRY_TABLE_META . " WHERE entry_id = %d\n\t\t\t\t\t\t\tORDER BY meta_key,meta_id", $id), ARRAY_A);
             if ($results !== FALSE) {
                 // Loop thru $results removing any custom meta fields. Custom meta fields are considered to be private.
                 foreach ($results as $metaID => $row) {
                     if (cnMeta::isPrivate($row['meta_key'])) {
                         unset($results[$row['meta_id']]);
                     }
                 }
                 // Loop thru the associated meta and update any that may have been changed.
                 // If the meta id doesn't exist in the $_POST data, assume the user deleted it.
                 foreach ($results as $metaID => $row) {
                     // Update the entry meta if it differs.
                     if (isset($_POST['meta'][$row['meta_id']]['value']) && $_POST['meta'][$row['meta_id']]['value'] !== $row['meta_value'] || isset($_POST['meta'][$row['meta_id']]['key']) && $_POST['meta'][$row['meta_id']]['key'] !== $row['meta_key'] && $_POST['meta'][$row['meta_id']]['value'] !== '::DELETED::') {
                         // If the key begins with an underscore, remove it because those are private.
                         //if ( isset( $row['key'][0] ) && '_' == $row['key'][0] ) $row['key'] = substr( $row['key'], 1 );
                         //cnMeta::update( 'entry', $id, $_POST['meta'][ $row['meta_id'] ]['key'], $_POST['meta'][ $row['meta_id'] ]['value'], $row['meta_value'], $row['meta_key'], $row['meta_id'] );
                         cnMeta::updateByID('entry', $row['meta_id'], $_POST['meta'][$row['meta_id']]['value'], $_POST['meta'][$row['meta_id']]['key']);
                         $metaIDs['updated'] = $row['meta_id'];
                     }
                     if (isset($_POST['meta'][$row['meta_id']]['value']) && $_POST['meta'][$row['meta_id']]['value'] === '::DELETED::') {
                         // Record entry meta to be deleted.
                         cnMeta::deleteByID('entry', $row['meta_id']);
                         $metaIDs['deleted'] = $row['meta_id'];
                     }
                 }
             }
             // Lastly, add any new meta the user may have added.
             if (isset($_POST['newmeta']) || !empty($_POST['newmeta'])) {
                 foreach ($_POST['newmeta'] as $row) {
                     // If the key begins with an underscore, remove it because those are private.
                     if (isset($row['key'][0]) && '_' == $row['key'][0]) {
                         $row['key'] = substr($row['key'], 1);
                     }
                     $metaIDs[] = cnMeta::add('entry', $id, $row['key'], $row['value']);
                 }
                 // $newmeta = cnMeta::add( 'entry', $id, $_POST['newmeta']['0']['key'], $_POST['newmeta']['99']['value'] );
             }
             if (isset($_POST['metakeyselect']) && $_POST['metakeyselect'] !== '-1') {
                 $metaSelect[] = cnMeta::add('entry', $id, $_POST['metakeyselect'], $_POST['newmeta']['99']['value']);
             }
             $metaIDs['added'] = array_merge($newmeta, $metaSelect);
             break;
     }
     return $metaIDs;
 }
 /**
  * Removes a term from the database.
  *
  * If the term is a parent of other terms, then the children will be updated to
  * that term's parent.
  *
  * The $args 'default' will only override the terms found, if there is only one
  * term found. Any other and the found terms are used.
  *
  * The $args 'force_default' will force the term supplied as default to be
  * assigned even if the object was not going to be termless
  *
  * NOTE: This is the Connections equivalent of @see wp_delete_term() in WordPress core ../wp-includes/taxonomy.php
  *
  * @access public
  * @since  8.1.6
  * @static
  *
  * @global wpdb $wpdb
  *
  * @uses   cnTerm::exists()
  * @uses   is_wp_error()
  * @uses   cnTerm::getBy()
  * @uses   wp_parse_args()
  * @uses   cnTerm::get()
  * @uses   wpdb::get_col()
  * @uses   wpdb::update()
  * @uses   do_action()
  * @uses   wpdb::prepare()
  * @uses   cnTerm::getRelationships()
  * @uses   cnTerm::setRelationships()
  * @uses   wpdb::delete()
  * @uses   wpdb::get_var()
  * @uses   cnTerm::cleanCache()
  *
  * @param int          $term     Term ID
  * @param string       $taxonomy Taxonomy Name
  * @param array|string $args     Optional. Change 'default' term id and override found term ids.
  *
  * @return bool|int|WP_Error Returns false if not term; true if completes delete action.
  */
 public static function delete($term, $taxonomy, $args = array())
 {
     global $wpdb;
     $term = (int) $term;
     if (!($ids = self::exists($term, $taxonomy))) {
         return FALSE;
     }
     if (is_wp_error($ids)) {
         return $ids;
     }
     $tt_id = $ids['term_taxonomy_id'];
     $defaults = array();
     if ('category' == $taxonomy) {
         $defaults['default'] = get_option('cn_default_category');
         // Don't delete the default category
         if ($defaults['default'] == $term) {
             return 0;
         }
     }
     $args = wp_parse_args($args, $defaults);
     if (isset($args['default'])) {
         $default = (int) $args['default'];
         if (!self::exists($default, $taxonomy)) {
             unset($default);
         }
     }
     if (isset($args['force_default'])) {
         $force_default = $args['force_default'];
     }
     /**
      * Fires when deleting a term, before any modifications are made to posts or terms.
      *
      * @since 8.5.10
      *
      * @param int    $term     Term ID.
      * @param string $taxonomy Taxonomy Name.
      */
     do_action('cn_pre_delete_term', $term, $taxonomy);
     //@todo Implement the is_taxonomy_hierarchical() conditional statement.
     // Update children to point to new parent
     //if ( is_taxonomy_hierarchical($taxonomy) ) {
     if (TRUE) {
         //temp hack...
         $term_obj = self::get($term, $taxonomy);
         if (is_wp_error($term_obj)) {
             return $term_obj;
         }
         $parent = $term_obj->parent;
         $edit_ids = $wpdb->get_results("SELECT term_id, term_taxonomy_id FROM " . CN_TERM_TAXONOMY_TABLE . " WHERE `parent` = " . (int) $term_obj->term_id);
         $edit_tt_ids = wp_list_pluck($edit_ids, 'term_taxonomy_id');
         /**
          * Fires immediately before a term to delete's children are reassigned a parent.
          *
          * @since 8.1.6
          *
          * @param array $edit_tt_ids An array of term taxonomy IDs for the given term.
          */
         do_action('cn_edit_term_taxonomies', $edit_tt_ids);
         $wpdb->update(CN_TERM_TAXONOMY_TABLE, compact('parent'), array('parent' => $term_obj->term_id) + compact('taxonomy'));
         // Clean the cache for all child terms.
         $edit_term_ids = wp_list_pluck($edit_ids, 'term_id');
         cnTerm::cleanCache($edit_term_ids, 'cn_' . $taxonomy);
         /**
          * Fires immediately after a term to delete's children are reassigned a parent.
          *
          * @since 8.1.6
          *
          * @param array $edit_tt_ids An array of term taxonomy IDs for the given term.
          */
         do_action('cn_edited_term_taxonomies', $edit_tt_ids);
     }
     // Get the object before deletion so we can pass to actions below
     $deleted_term = self::get($term, $taxonomy);
     $objects = $wpdb->get_col($wpdb->prepare("SELECT entry_id FROM " . CN_TERM_RELATIONSHIP_TABLE . " WHERE term_taxonomy_id = %d", $tt_id));
     foreach ((array) $objects as $object) {
         $terms = self::getRelationships($object, $taxonomy, array('fields' => 'ids', 'orderby' => 'none'));
         if (1 == count($terms) && isset($default)) {
             $terms = array($default);
         } else {
             $terms = array_diff($terms, array($term));
             if (isset($default) && isset($force_default) && $force_default) {
                 $terms = array_merge($terms, array($default));
             }
         }
         $terms = array_map('intval', $terms);
         self::setRelationships($object, $terms, $taxonomy);
     }
     // Clean the relationship caches for all object types using this term
     //@todo Implement the following block of code.
     //$tax_object = get_taxonomy( $taxonomy );
     //foreach ( $tax_object->object_type as $object_type )
     //	self::cleanRelationshipCache( $objects, $object_type );
     self::cleanRelationshipCache($objects, $taxonomy);
     // Clean the entry/term relationships directly until get_taxonomy() is implemented.
     $term_meta_ids = $wpdb->get_col($wpdb->prepare("SELECT meta_id FROM {$wpdb->termmeta} WHERE term_id = %d ", $term));
     foreach ($term_meta_ids as $mid) {
         cnMeta::deleteByID('term', $mid);
     }
     /**
      * Fires immediately before a term taxonomy ID is deleted.
      *
      * @since 8.1.6
      *
      * @param int $tt_id Term taxonomy ID.
      */
     do_action('cn_delete_term_taxonomy', $tt_id);
     $wpdb->delete(CN_TERM_TAXONOMY_TABLE, array('term_taxonomy_id' => $tt_id));
     /**
      * Fires immediately after a term taxonomy ID is deleted.
      *
      * @since 8.1.6
      *
      * @param int $tt_id Term taxonomy ID.
      */
     do_action('cn_deleted_term_taxonomy', $tt_id);
     // Delete the term if no taxonomies use it.
     if (!$wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM " . CN_TERM_TAXONOMY_TABLE . " WHERE term_id = %d", $term))) {
         $wpdb->delete(CN_TERMS_TABLE, array('term_id' => $term));
     }
     self::cleanCache($term, $taxonomy);
     /**
      * Fires after a term is deleted from the database and the cache is cleaned.
      *
      * @since 8.1.6
      *
      * @param int    $term          Term ID.
      * @param int    $tt_id         Term taxonomy ID.
      * @param string $taxonomy      Taxonomy slug.
      * @param mixed  $deleted_term  Copy of the already-deleted term, in the form specified
      *                              by the parent function. WP_Error otherwise.
      */
     do_action('cn_delete_term', $term, $tt_id, $taxonomy, $deleted_term);
     /**
      * Fires after a term in a specific taxonomy is deleted.
      *
      * The dynamic portion of the hook name, $taxonomy, refers to the specific
      * taxonomy the term belonged to.
      *
      * @since 8.1.6
      *
      * @param int   $term           Term ID.
      * @param int   $tt_id          Term taxonomy ID.
      * @param mixed $deleted_term   Copy of the already-deleted term, in the form specified
      *                              by the parent function. WP_Error otherwise.
      */
     // @todo Re-implement the action, currently it conflicts with the `cn_delete_category` action in:
     // ../includes/admin/class.actions.php
     //do_action( "cn_delete_$taxonomy", $term, $tt_id, $deleted_term );
     return TRUE;
 }