/**
     * Callback to render the "Custom Fields" metabox.
     *
     * @access private
     * @since 0.8
     * @param  cnEntry $entry   An instance of the cnEntry object.
     * @param  array  $metabox The metabox attributes array set in self::register().
     * @return void
     */
    public static function meta($entry, $metabox)
    {
        /** @var wpdb $wpdb */
        global $wpdb;
        $results = $wpdb->get_results($wpdb->prepare("SELECT meta_key, meta_value, meta_id, entry_id\n\t\t\tFROM " . CN_ENTRY_TABLE_META . " WHERE entry_id = %d\n\t\t\tORDER BY meta_key,meta_id", $entry->getId()), ARRAY_A);
        $metabox = $metabox['args'];
        $keys = cnMeta::key('entry');
        $options = array();
        // Toss the meta that is saved as part of a custom field.
        if (!empty($results)) {
            foreach ($results as $metaID => $meta) {
                if (cnMeta::isPrivate($meta['meta_key'])) {
                    unset($results[$metaID]);
                }
            }
        }
        // Build the meta key select drop down options.
        if (!empty($keys)) {
            $options = array_combine(array_map('esc_attr', array_keys($keys)), array_map('esc_html', $keys));
            array_walk($options, create_function('&$key', '$key = "<option value=\\"$key\\">$key</option>";'));
        }
        array_unshift($options, '<option value="-1">&mdash; ' . __('Select', 'connections') . ' &mdash;</option>');
        $options = implode($options, PHP_EOL);
        // echo '<input type="hidden" name="wp_meta_box_nonce" value="', wp_create_nonce( basename(__FILE__) ), '" />';
        echo '<div class="cn-metabox-section" id="meta-fields">';
        ?>

		<table id="list-table" style="<?php 
        echo empty($results) ? 'display: none;' : 'display: table;';
        ?>
">
			<thead>
				<tr>
					<th class="left"><?php 
        _e('Name', 'connections');
        ?>
</th>
					<th><?php 
        _e('Value', 'connections');
        ?>
</th>
				</tr>
			</thead>

			<tbody id="the-list">

			<?php 
        if (!empty($results)) {
            foreach ($results as $metaID => $meta) {
                // Class added to alternate tr rows for CSS styling.
                $alternate = !isset($alternate) || $alternate == '' ? 'alternate' : '';
                ?>

					<tr id="meta-<?php 
                echo $meta['meta_id'];
                ?>
" class="<?php 
                echo $alternate;
                ?>
">

						<td class="left">
							<label class="screen-reader-text" for='meta[<?php 
                echo $meta['meta_id'];
                ?>
][key]'><?php 
                _e('Key', 'connections');
                ?>
</label>
							<input name='meta[<?php 
                echo $meta['meta_id'];
                ?>
][key]' id='meta[<?php 
                echo $meta['meta_id'];
                ?>
][key]' type="text" size="20" value="<?php 
                echo esc_textarea($meta['meta_key']);
                ?>
" />
							<div class="submit">
								<input type="submit" name="deletemeta[<?php 
                echo $meta['meta_id'];
                ?>
]" id="deletemeta[<?php 
                echo $meta['meta_id'];
                ?>
]" class="button deletemeta button-small" value="<?php 
                _e('Delete', 'connections');
                ?>
" />
							</div>
						</td>

						<td>
							<label class="screen-reader-text" for='meta[<?php 
                echo $meta['meta_id'];
                ?>
][value]'><?php 
                _e('Value', 'connections');
                ?>
</label>
							<textarea name='meta[<?php 
                echo $meta['meta_id'];
                ?>
][value]' id='meta[<?php 
                echo $meta['meta_id'];
                ?>
][value]' rows="2" cols="30"><?php 
                echo esc_textarea(cnFormatting::maybeJSONencode($meta['meta_value']));
                ?>
</textarea>
						</td>

					</tr>

					<?php 
            }
            ?>

			<?php 
        }
        ?>

			<!-- This is the row that will be cloned via JS when adding a new Custom Field. -->
			<tr style="display: none;">

				<td class="left">
					<label class="screen-reader-text" for='newmeta[0][key]'><?php 
        _e('Key', 'connections');
        ?>
</label>
					<input name='newmeta[0][key]' id='newmeta[0][key]' type="text" size="20" value=""/>
					<div class="submit">
						<input type="submit" name="deletemeta[0]" id="deletemeta[0]" class="button deletemeta button-small" value="<?php 
        _e('Delete', 'connections');
        ?>
" />
						<!-- <input type="submit" name="newmeta-0-submit" id="newmeta-0-submit" class="button updatemeta button-small" value="Update" /> -->
					</div>
					<!-- <input type="hidden" id="_ajax_nonce" name="_ajax_nonce" value="0db0025bba" /> -->
				</td>
				<td>
					<label class="screen-reader-text" for='newmeta[0][value]'><?php 
        _e('Value', 'connections');
        ?>
</label>
					<textarea name='newmeta[0][value]' id='newmeta[0][value]' rows="2" cols="30"></textarea>
				</td>

			</tr>

			</tbody>
		</table>

		<p><strong><?php 
        _e('Add New Custom Field:', 'connections');
        ?>
</strong></p>

		<table id="newmeta">
			<thead>
				<tr>
					<th class="left"><label for="metakeyselect"><?php 
        _e('Name', 'connections');
        ?>
</label></th>
					<th><label for="metavalue"><?php 
        _e('Value', 'connections');
        ?>
</label></th>
				</tr>
			</thead>
			<tbody>

				<tr>

					<td id="newmetaleft" class="left">
						<select id="metakeyselect" name="metakeyselect">
							<?php 
        echo $options;
        ?>
						</select>
						<input class="hide-if-js" type=text id="metakeyinput" name="newmeta[99][key]" value=""/>
						<a href="#postcustomstuff" class="postcustomstuff hide-if-no-js"> <span id="enternew"><?php 
        _e('Enter New', 'connections');
        ?>
</span> <span id="cancelnew" class="hidden"><?php 
        _e('Cancel', 'connections');
        ?>
</span></a>
					</td>

					<td>
						<textarea id="metavalue" name="newmeta[99][value]" rows="2" cols="25"></textarea>
					</td>

				</tr>



			</tbody>
			<tfoot>
				<td colspan="2">
					<div class="submit">
						<input type="submit" name="addmeta" id="newmeta-submit" class="button" value="<?php 
        _e('Add Custom Field', 'connections');
        ?>
" />
					</div>
					<!-- <input type="hidden" id="_ajax_nonce-add-meta" name="_ajax_nonce-add-meta" value="a7f70d2878" /> -->
				</td>
			</tfoot>
		</table>

		<?php 
        if (isset($metabox['desc']) && !empty($metabox['desc'])) {
            printf('<p>%1$s</p>', esc_html($metabox['desc']));
        }
        echo '</div>';
    }
 /**
  * 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;
 }
 /**
  * Outputs the data saved in the "Custom Fields" entry metabox.
  * This should not be confused with the fields registered with
  * cnMetaboxAPI. Those fields should be output using a registered
  * action which runs in $this->getMetaBlock().
  *
  * @access private
  * @since 0.8
  * @uses wp_parse_args()
  * @uses apply_filters()
  * @param  array  $metadata The metadata array passed from $this->getMetaBlock(). @see self::getMetaBlock().
  *
  * @return string
  */
 private function renderMetaBlock($metadata)
 {
     $out = '';
     $defaults = array('container_tag' => 'ul', 'item_tag' => 'li', 'key_tag' => 'span', 'value_tag' => 'span', 'separator' => ': ', 'before' => '', 'after' => '');
     $atts = wp_parse_args(apply_filters('cn_output_meta_atts', $defaults), $defaults);
     foreach ((array) $metadata as $key => $value) {
         // Do not render any private keys; ie. ones that begin with an underscore
         // or any fields registered as part of a custom metabox.
         if (cnMeta::isPrivate($key, 'entry')) {
             continue;
         }
         $out .= apply_filters('cn_entry_output_meta_key', sprintf('<%1$s><%2$s class="cn-entry-meta-key">%3$s%4$s</%2$s><%5$s class="cn-entry-meta-value">%6$s</%5$s></%1$s>' . PHP_EOL, $atts['item_tag'], $atts['key_tag'], trim($key), $atts['separator'], $atts['value_tag'], implode(', ', (array) $value)), $atts, $key, $value);
     }
     if (empty($out)) {
         return '';
     }
     $out = apply_filters('cn_entry_output_meta_container', sprintf('<%1$s class="cn-entry-meta">%2$s</%1$s>' . PHP_EOL, $atts['container_tag'], $out), $atts, $metadata);
     echo $atts['before'] . $out . $atts['after'] . PHP_EOL;
 }