Skip to content

Instantly share code, notes, and snippets.

@jlambe
Created October 7, 2015 05:23
Show Gist options
  • Save jlambe/fc4f23a580f9fe3c74fd to your computer and use it in GitHub Desktop.
Save jlambe/fc4f23a580f9fe3c74fd to your computer and use it in GitHub Desktop.
Taxonomy custom fields. Handles only text and media fields. Values are saved inside the options table.
<?php
namespace Themosis\Taxonomy;
/**
* TaxField class
*
* Allow the user to add custom fields to a taxonomy.
*/
class TaxField
{
/**
* The taxonomy slug.
*
* @var string
* @access private
*/
private $slug;
/**
* Tell if the taxonomy exists.
*
* @var boolean
* @access private
*/
private $exists = false;
/**
* The custom fields of the taxonomy.
*
* @var array
* @access private
*/
private $fields = array();
/**
* The TaxField constructor.
*
* @param string $taxonomySlug The taxonomy slug used by action hooks.
*/
private function __construct($taxonomySlug)
{
$this->slug = $taxonomySlug;
/*-----------------------------------------------------------------------*/
// Check if the taxonomy exists before going further.
/*-----------------------------------------------------------------------*/
add_action('wp_loaded', array($this, 'check'));
}
/**
* Init the custom taxonomy field.
*
* @param string $taxonomySlug The taxonomy slug.
* @throws TaxonomyException
* @return \Themosis\Taxonomy\TaxField
*/
public static function make($taxonomySlug)
{
$slug = trim($taxonomySlug);
if (!empty($slug) && is_string($slug)) {
return new static($slug);
} else {
throw new TaxonomyException("String expected as a parameter.");
}
}
/**
* Check if the taxonomy exists. Call by the action hook 'wp_loaded'.
* If not, throw an exception.
*
* @throws TaxonomyException
* @return void
* @ignore
*/
public function check()
{
if (taxonomy_exists($this->slug)) {
/*-----------------------------------------------------------------------*/
// Set the exists property to true.
// Allow the user to define the fields later with the "set" method.
/*-----------------------------------------------------------------------*/
$this->exists = true;
} else {
throw new TaxonomyException('The taxonomy slug "'.$this->slug.'" does not exists.');
}
}
/**
* Set the custom fields for the taxonomy.
*
* @param array $fields A list of fields.
* @throws TaxonomyException
* @return \Themosis\Taxonomy\TaxField
*/
public function set(array $fields)
{
if (is_array($fields) && !empty($fields)) {
/*-----------------------------------------------------------------------*/
// Parse the fields and save them to the instance property.
/*-----------------------------------------------------------------------*/
$this->fields = $this->parse($fields, $this->slug);
/*-----------------------------------------------------------------------*/
// Add the field to the "add term page"
// {$taxonomy_slug}_add_form_fields
/*-----------------------------------------------------------------------*/
$slug = $this->slug.'_add_form_fields';
add_action($slug, array($this, 'addFields'));
/*-----------------------------------------------------------------------*/
// Add the field to the "edit term page"
/*-----------------------------------------------------------------------*/
$slug = $this->slug.'_edit_form_fields';
add_action($slug, array($this, 'editFields'));
/*-----------------------------------------------------------------------*/
// Register the save hooks on the add + edit pages.
/*-----------------------------------------------------------------------*/
add_action('edited_'.$this->slug, array($this, 'save'), 10, 2);
add_action('create_'.$this->slug, array($this, 'save'), 10, 2);
/*-----------------------------------------------------------------------*/
// Register the delete hook in order to remove the custom fields
// from the options table.
/*-----------------------------------------------------------------------*/
add_action('delete_term', array($this,'delete'), 10,2);
return $this;
} else {
throw new TaxonomyException('Array expected as a parameter.');
}
}
/**
* Display the custom fields on the add terms page.
*
* @return void
* @ignore
*/
public function addFields()
{
/*-----------------------------------------------------------------------*/
// Output the custom fields
/*-----------------------------------------------------------------------*/
TaxFieldRenderer::render('add', $this->fields);
}
/**
* Display the custom fields on the edit term page.
*
* @param \stdClass $term The term object passed by WordPress.
* @return void
* @ignore
*/
public function editFields(\stdClass $term)
{
/*-----------------------------------------------------------------------*/
// Output the custom fields
/*-----------------------------------------------------------------------*/
TaxFieldRenderer::render('edit', $this->fields, $term);
}
/**
* Save the fields values in the options table.
*
* @param int $term_id The term ID.
* @return void
* @ignore
*/
public function save($term_id)
{
if (isset($_POST[$this->slug])) {
/*-----------------------------------------------------------------------*/
// Option unique key
/*-----------------------------------------------------------------------*/
$optionKey = $this->slug.'_'.$term_id;
/*-----------------------------------------------------------------------*/
// Retrieve an existing value if it exists...
/*-----------------------------------------------------------------------*/
$term_meta = get_option($optionKey);
/*-----------------------------------------------------------------------*/
// Get all fields names's key
/*-----------------------------------------------------------------------*/
$cat_keys = array_keys($_POST[$this->slug]);
foreach ($cat_keys as $key) {
if (isset($_POST[$this->slug][$key])) {
$term_meta[$key] = $_POST[$this->slug][$key];
}
}
/*-----------------------------------------------------------------------*/
// Save the fields
/*-----------------------------------------------------------------------*/
update_option($optionKey, $term_meta );
}
}
/**
* Delete the fields from the database.
*
* @param \stdClass $term The term object.
* @param int $term_id The term ID.
* @return void
* @ignore
*/
public function delete(\stdClass $term, $term_id)
{
$key = $this->slug.'_'.$term_id;
delete_option($key);
}
/**
* Parse the fields and mix them with a default one.
*
* @param array $fields The defined fields and their properties.
* @param string $taxonomySlug The taxonomy slug.
* @return array The parsed array of fields with a TaxonomySlug key/value.
*/
private function parse(array $fields, $taxonomySlug)
{
$newFields = array();
foreach ($fields as $field) {
$defaults = array(
'name' => 'default_field',
'title' => ucfirst($field['name']),
'info' => '',
'default' => '',
'type' => 'text',
'options' => array(),
'class' => '',
'multiple' => false,
'fields' => array(),
'taxonomy_slug' => $taxonomySlug
);
/*-----------------------------------------------------------------------*/
// Mix values from defaults and $args and then extract
// the results as $variables
/*-----------------------------------------------------------------------*/
extract(wp_parse_args($field, $defaults));
$field_args = array(
'type' => $type,
'name' => $name,
'info' => $info,
'default' => $default,
'options' => $options,
'label_for' => $name,
'class' => $class,
'title' => $title,
'multiple' => $multiple,
'fields' => $fields,
'taxonomy_slug' => $taxonomy_slug
);
/*-----------------------------------------------------------------------*/
// Add new settings
/*-----------------------------------------------------------------------*/
$newFields[] = $field_args;
}
return $newFields;
}
}
<?php
namespace Themosis\Taxonomy;
/**
* TaxFieldRenderer class
*
* Utility class that output html in order to display
* the custom fields of the taxonomies.
*
*/
class TaxFieldRenderer
{
/**
* Handle output for the "add term" page.
*
* @param string $typeOfPage Type of the page where to output the field - Accepted values : 'add', 'edit'.
* @param array $fields The fields to output.
* @param \stdClass $term The term object sent by WordPress.
* @return void
*/
public static function render($typeOfPage, array $fields, \stdClass $term = null)
{
foreach ($fields as $field):
/*-----------------------------------------------------------------------*/
// Output the custom field
/*-----------------------------------------------------------------------*/
switch ($field['type']) {
/*-----------------------------------------------------------------------*/
// Text input field
/*-----------------------------------------------------------------------*/
case 'text':
static::text($typeOfPage, $field, $term);
break;
/*-----------------------------------------------------------------------*/
// Media custom field
/*-----------------------------------------------------------------------*/
case 'media':
static::media($typeOfPage, $field, $term);
break;
default:
break;
}
endforeach;
}
/**
* Helper function that checks the page type.
*
* @param string $typeOfPage Type of the page: 'add' or 'edit'.
* @return bool True. False if not the 'add' page.
*/
private static function isAddPage($typeOfPage)
{
if ($typeOfPage === 'add') {
return true;
}
return false;
}
/**
* Open tags for the 'Add term' page.
*
* @param string $name The name attribute of the custom field.
* @param string $title The title property of the custom field.
* @return void
*/
private static function openTagsForAddPage($name, $title)
{
?>
<div class="form-field">
<label for="<?php echo($name); ?>-field"><?php echo($title); ?></label>
<?php
}
/**
* Close tags for the 'Add term' page.
*
* @return void
*/
private static function closeTagsForAddPage()
{
?>
</div>
<?php
}
/**
* Open tags for the 'Edit term' page.
*
* @param string $name The name attribute of the custom field.
* @param string $title The title property of the custom field.
* @return void
*/
private static function openTagsForEditPage($name, $title)
{
?>
<tr class="form-field">
<th scope="row" valign="top">
<label for="<?php echo($name); ?>-field"><?php echo($title); ?></label>
</th>
<td>
<?php
}
/**
* Close tags for the 'Edit term' page.
*
* @return void
*/
private static function closeTagsForEditPage()
{
?>
</td>
</tr>
<?php
}
/**
* Display the 'info' html tags.
*
* @param string $typeOfPage Type of page: 'edit' or 'add'.
* @param string $info The info text to display.
* @return void
*/
private static function infos($typeOfPage, $info)
{
/*-----------------------------------------------------------------------*/
// ADD page description
/*-----------------------------------------------------------------------*/
if (static::isAddPage($typeOfPage)) {
if (isset($info) && !empty($info)):
?>
<p><?php echo(ucfirst($info)); ?></p>
<?php
endif;
/*-----------------------------------------------------------------------*/
// EDIT page description
/*-----------------------------------------------------------------------*/
} else {
if (isset($info) && !empty($info)):
?>
<span class="description"><?php echo(ucfirst($info)); ?></span>
<?php
endif;
}
}
/**
* Render a text field.
*
* @param string $typeOfPage Which page is viewed: 'add' or 'edit'.
* @param array $field The field properties.
* @param \stdClass $term The term object sent by WordPress.
* @return void
*/
private static function text($typeOfPage, array $field, \stdClass $term = null)
{
extract($field);
/*-----------------------------------------------------------------------*/
// HTML output for the add term page.
/*-----------------------------------------------------------------------*/
if (static::isAddPage($typeOfPage)):
/*-----------------------------------------------------------------------*/
// Open tags
/*-----------------------------------------------------------------------*/
static::openTagsForAddPage($name, $title);
?>
<input type="text" id="<?php echo($name); ?>-field" name="<?php echo($taxonomy_slug.'['.$name.']'); ?>" value="" size="40"/>
<?php
/*-----------------------------------------------------------------------*/
// Infos
/*-----------------------------------------------------------------------*/
static::infos($typeOfPage, $info);
/*-----------------------------------------------------------------------*/
// Close tags
/*-----------------------------------------------------------------------*/
static::closeTagsForAddPage();
/*-----------------------------------------------------------------------*/
// HTML output for the edit term page.
/*-----------------------------------------------------------------------*/
else:
/*-----------------------------------------------------------------------*/
// Retrieve the value for this field if it exists.
/*-----------------------------------------------------------------------*/
$optionkey = $taxonomy_slug.'_'.$term->term_id;
// Array of values of all taxonomy fields.
$values = get_option($optionkey);
// Get the field value and check if it is set.
$value = isset($values[$name]) ? $values[$name] : '';
/*-----------------------------------------------------------------------*/
// Open tags
/*-----------------------------------------------------------------------*/
static::openTagsForEditPage($name, $title);
?>
<input type="text" id="<?php echo($name); ?>-field" name="<?php echo($taxonomy_slug.'['.$name.']'); ?>" value="<?php if (isset($value) && !empty($value)) { echo($value); } ?>" size="40" />
<br />
<?php
/*-----------------------------------------------------------------------*/
// Infos
/*-----------------------------------------------------------------------*/
static::infos($typeOfPage, $info);
/*-----------------------------------------------------------------------*/
// Close tags
/*-----------------------------------------------------------------------*/
static::closeTagsForEditPage();
endif;
}
/**
* Render a Media field.
*
* @param string $typeOfPage Which page is viewed: 'add' or 'edit'.
* @param array $field The field properties.
* @param \stdClass $term The term object sent by WordPress.
* @return void
*/
private static function media($typeOfPage, array $field, \stdClass $term = null)
{
extract($field);
/*-----------------------------------------------------------------------*/
// HTML output for the add term page.
/*-----------------------------------------------------------------------*/
if (static::isAddPage($typeOfPage)):
/*-----------------------------------------------------------------------*/
// Open tags
/*-----------------------------------------------------------------------*/
static::openTagsForAddPage($name, $title);
?>
<table class="themosis-media-table">
<tbody>
<tr class="themosis-field-media">
<td class="themosis-media-input">
<input type="text" size="40" name="<?php echo($taxonomy_slug.'['.$name.']'); ?>" id="<?php echo($name); ?>-field" />
</td>
<td>
<button type="button" class="button-primary themosis-media-button" id="themosis-media-add"><?php _e('Add', THEMOSIS_FRAMEWORK_TEXTDOMAIN); ?></button>
</td>
<td>
<button type="button" class="button themosis-media-clear" id="themosis-media-clear"><?php _e('Clear', THEMOSIS_FRAMEWORK_TEXTDOMAIN); ?></button>
</td>
</tr>
</tbody>
</table>
<?php
/*-----------------------------------------------------------------------*/
// Infos
/*-----------------------------------------------------------------------*/
static::infos($typeOfPage, $info);
/*-----------------------------------------------------------------------*/
// Close tags
/*-----------------------------------------------------------------------*/
static::closeTagsForAddPage();
/*-----------------------------------------------------------------------*/
// HTML output for the edit term page.
/*-----------------------------------------------------------------------*/
else:
/*-----------------------------------------------------------------------*/
// Retrieve the value for this field if it exists.
/*-----------------------------------------------------------------------*/
$optionkey = $taxonomy_slug.'_'.$term->term_id;
// Array of values of all taxonomy fields.
$values = get_option($optionkey);
// Get the field value and check if it is set.
$value = isset($values[$name]) ? $values[$name] : '';
/*-----------------------------------------------------------------------*/
// Open tags
/*-----------------------------------------------------------------------*/
static::openTagsForEditPage($name, $title);
?>
<table class="themosis-media-table">
<tbody>
<tr class="themosis-field-media">
<td class="themosis-media-input">
<input type="text" size="40" name="<?php echo($taxonomy_slug.'['.$name.']'); ?>" id="<?php echo($name); ?>-field" value="<?php if (isset($value) && !empty($value)) { echo($value); } ?>" />
</td>
<td>
<button type="button" class="button-primary themosis-media-button" id="themosis-media-add"><?php _e('Add', THEMOSIS_FRAMEWORK_TEXTDOMAIN); ?></button>
</td>
<td>
<button type="button" class="button themosis-media-clear" id="themosis-media-clear"><?php _e('Clear', THEMOSIS_FRAMEWORK_TEXTDOMAIN); ?></button>
</td>
</tr>
</tbody>
</table>
<?php
/*-----------------------------------------------------------------------*/
// Infos
/*-----------------------------------------------------------------------*/
static::infos($typeOfPage, $info);
/*-----------------------------------------------------------------------*/
// Close tags
/*-----------------------------------------------------------------------*/
static::closeTagsForEditPage();
endif;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment