Skip to content

Instantly share code, notes, and snippets.

@DavidWiesner
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DavidWiesner/a9447fe2be95cefd2ba8 to your computer and use it in GitHub Desktop.
Save DavidWiesner/a9447fe2be95cefd2ba8 to your computer and use it in GitHub Desktop.
Builder Pattern for Wordpress MetaBox plugin see cpt-persons.php and page-person.php for usage
<?php
function post_persons() {
$labels = array(
'name' => _x('Persons', 'post type general name'),
'singular_name' => _x('Person', 'post type single name'),
);
$args = array(
'labels' => $labels,
'description' => 'Persons in Team',
'hierarchical' => false,
'public' => true,
'menu_position' => 5,
'supports' => array( 'title', 'thumbnail' ),
'has_archive' => true,
'menu_icon' => 'dashicons-groups',
'rewrite' => array( 'slug' => 'persons-all' ),
);
register_post_type('person', $args);
}
add_action('init', 'post_persons');
/**
* And Here comes the interessting part
**/
// Create new Builder
$PersonMetaBuilder = new Metabox_Builder('Person_Prefix_', __('Memberinformation', 'rwmb'), array( 'person' ));
// add filed, set required with error message
$PersonMetaBuilder->new_field('givennames', __('Givennames', 'rwmb'), 'text', __('Lucia', 'rwmb'))->set_required("Nobody has no Givenname");
// works also ass a chain ->new_field(...)->new_field(...)->new_field(...)
$PersonMetaBuilder->new_field('surname', __('Surname', 'rwmb'), 'text', __('Moholy', 'rwmb'))->set_required()
// field with additional option 'raw' and 'options'
->new_field('description', __('Description', 'rwmb'), 'wysiwyg')->with_option('raw', false)->with_option('options', array( 'textarea_rows' => 1, 'media_buttons' => false ))
// field with additional options set as an array
->new_field('seconddesc', __('Second', 'rwmb'), 'wysiwyg')->set_options(array( 'raw' => true, 'options' => array( 'textarea_rows' => 2, 'media_buttons' => false ) ))
->new_field('phone', __('Phone', 'rwmb'), 'text', '+385 22 44 60 25')
->new_field('fax', __('Fax', 'rwmb'), 'text', '+385 22 44 60 43')
->new_field('email', __('Email', 'rwmb'), 'email')
->new_field('age', __('Age', 'rwmb'), 'number')->set_options(array( 'min' => 18, 'placeholder' => 21 ))
->new_field('twins', __('Twins', 'rwmb'), 'number')->with_option('step', 2)
->new_field('song', __('Song', 'rwmb'), 'file')->with_option('max_file_uploads', 1)
// validate as url with error message
->new_field('homepage', __('Homepage', 'rwmb'), 'url')->validate('url', true, __('<i>Your Homepage should be an Url</i>', 'rwmb'));
// create a class to use in a page to get or echo the meta field vales
// for details see page-person.php
$PersonsMeta = $PersonMetaBuilder->create();
<?php
/*
* Copyright (C) 2015 David Wiesner
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
if (!class_exists('Metabox_Builder')) {
class Metabox_Field_Builder {
protected $parent_builder;
protected $options = array();
protected $rules = array();
protected $messages = array();
/*
* @param id id of the field. Required. Prefix will be added automatical. Must be unique. It will be used as meta_key. It´s a good practice to use only numbers, chars and underscores.
* @param name name of the custom field. It´ll be displayed in the meta box. Required.
* @param type field type. See the list below for all supported field types. Required.
* @param desc a short description explaining what it is. Optional.
* @param std default value of the custom field. Optional.
* @param class custom CSS class, in case you want to style the field the way you want. Optional.
* @param clone is the field clonable? true or false. Optional. Note that this feature currently works for almost all fields, except file and image fields.
*/
function __construct($parent_builder, $id, $name, $type, $desc, $std = '', $class = '', $clone = false) {
$this->parent_builder = $parent_builder;
$this->options = array('id' => $parent_builder->get_prefix() . $id,
'name' => $name, 'type' => $type, 'desc' => $desc,
'std' => $std, 'class' => $class, 'clone' => $clone);
}
function with_option($key, $value) {
$this->options[$key] = $value;
return $this;
}
function set_options($options){
$this->options = array_merge($this->options, $options);
return $this;
}
function validate($option, $value, $message = null) {
$this->rules[$option] = $value;
if ($message != null) {
$this->messages[$option] = $message;
}
return $this;
}
function set_required($message = null) {
$this->validate('required', true, $message);
return $this;
}
/*
* @param id id of the field. Required. Must be unique. It will be used as meta_key. It´s a good practice to use only numbers, chars and underscores.
* @param name name of the custom field. It´ll be displayed in the meta box. Required.
* @param type field type. See the list below for all supported field types. Required.
* @param desc a short description explaining what it is. Optional.
* @param std default value of the custom field. Optional.
* @param class custom CSS class, in case you want to style the field the way you want. Optional.
* @param clone is the field clonable? true or false. Optional. Note that this feature currently works for almost all fields, except file and image fields.
*/
function new_field($id, $name, $type, $desc = '', $std = '', $class = '', $clone = false) {
return $this->parent_builder->new_field($id, $name, $type, $desc, $std, $class, $clone);
}
function create() {
return $this->parent_builder->create();
}
/**
* @return array
*/
public function get_options() {
return $this->options;
}
/**
* @return array
*/
public function get_rules() {
return $this->rules;
}
/**
* @return array
*/
public function get_messages() {
return $this->messages;
}
}
class Metabox_Builder {
protected $prefix;
protected $title;
protected $post_types;
protected $context;
protected $priority;
protected $fields = array();
protected $validation = array('rules' => array(), 'messages' => array());
protected $current_field;
/*
* @param prefix prefixe for all generated fields
* @param title Meta box title. Required.
* @param post_types Custom post types which the meta box is for. Can be array for multiple custom post types or string for single post type. Optional.
* @param context Part of the page where the meta box is displayed (normal, advanced or side). Optional. Default: normal.
* @param priority Priority within the context where the box is displayed (high or low). Optional. Default: high.
*/
function __construct($prefix, $title, $post_types = 'post', $context = 'normal', $priority = 'high') {
$this->prefix = $prefix;
$this->title = $title;
$this->post_types = $post_types;
$this->context = $context;
$this->priority = $priority;
}
/*
* @param id id of the field. Required. Must be unique. It will be used as meta_key. It´s a good practice to use only numbers, chars and underscores.
* @param name name of the custom field. It´ll be displayed in the meta box. Required.
* @param type field type. See the list below for all supported field types. Required.
* @param desc a short description explaining what it is. Optional.
* @param std default value of the custom field. Optional.
* @param class custom CSS class, in case you want to style the field the way you want. Optional.
* @param clone is the field clonable? true or false. Optional. Note that this feature currently works for almost all fields, except file and image fields.
*/
function new_field($id, $name, $type, $desc = '', $std = '', $class = '', $clone = false) {
$this->add_current_field();
// TODO switch by type
$this->current_field = new Metabox_Field_Builder($this, $id, $name, $type, $desc, $std, $class, $clone);
return $this->current_field;
}
protected function add_field($field_options, $rules = null, $messages = null) {
$this->fields[] = $field_options;
$this->add_validation($field_options['id'], $rules, $messages);
return $this;
}
function add_validation($field_id, $rules = null, $messages = null) {
if ($rules != null) {
$this->validation["rules"][$field_id] = $rules;
if ($messages != null) {
$this->validation["messages"][$field_id] = $messages;
}
}
return $this;
}
function get_prefix() {
return $this->prefix;
}
function register_meta_boxes($meta_boxes) {
$meta_boxes[] = array(
'title' => $this->title,
'post_types' => $this->post_types,
'context' => $this->context,
'priority' => $this->priority,
'fields' => $this->fields,
'validation' => $this->validation);
return $meta_boxes;
}
function create() {
$this->add_current_field();
$field_types = array();
foreach ($this->fields as $field) {
$field_types[$field['id']] = $field['type'];
}
add_filter('rwmb_meta_boxes', array($this, 'register_meta_boxes'));
return new Generic_Metabox_Getter($this->get_prefix(), $field_types);
}
protected function add_current_field() {
if ($this->current_field != null) {
$this->add_field($this->current_field->get_options(),
$this->current_field->get_rules(),
$this->current_field->get_messages());
$this->current_field = null;
}
}
}
class Generic_Metabox_Getter {
protected $prefix;
protected $field_types;
function __construct($prefix, $field_types) {
$this->prefix = $prefix;
$this->field_types = $field_types;
}
public function __get($property) {
$id = $this->prefix . $property;
if (isset($this->field_types[$id])) {
return rwmb_meta($id, 'type=' . $this->field_types[$id]);
}
}
/**
* generic getter for values
* call $this->get_logo(array('size'=>100)) will result in rwmb_meta('PREFIX_logo', array('type'=>'image', 'size'=>100))
*
*/
public function __call($name, $arguments) {
if (preg_match('/^get_(.+)/', $name, $matches)) {
$id = $this->prefix . $matches[1];
$options = (count($arguments) > 0 and is_array($arguments[0])) ? $arguments[0] : array();
if (!isset($options['type'])) {
$options['type'] = $this->field_types[$id];
}
if (isset($this->field_types[$id])) {
return rwmb_meta($id, http_build_query($options));
}
}
if (preg_match('/^echo_(.+)/', $name, $matches)) {
echo($this->__call('get_' . $matches[1], $arguments));
return;
}
}
}
}
<?php
/**
* Template Name: Person
* Persons Template Page
*
* @package WordPress
* @subpackage Boilerplate
* @since Boilerplate 1.0
*/
get_header();
$args = array(
'posts_per_page' => -1,
'post_type' => 'person',
);
$team_array = new WP_Query( $args );
if( $team_array->have_posts() ) {
while( $team_array->have_posts() ) {
$team_array->the_post();
?>
<div id="<?php echo 'person-'.$post->ID ?>">
<div class="thumbnail_member">
<?php if ( has_post_thumbnail() ) { the_post_thumbnail('album-grid', array('class'=>'photo')); }?>
</div>
<div>
<h2 class="fullname">
<?php the_title() ?>
</h2>
<div>
<?php $PersonsMeta->echo_description(); ?>
</div>
<div>Tel:
<?php $PersonsMeta->echo_phone(); ?>
</div>
<div>
<?php if($PersonsMeta->get_fax()) echo('Fax: '.$PersonsMeta->get_fax()); ?>
</span></div>
<div>
<a class="email" href="mailto:<?php $PersonsMeta->echo_email(); ?>">
<?php $PersonsMeta->echo_email();?>
</a>
</div>
</div>
<br class="clear"/>
</div>
<?php
}
} else {
echo '<div><h2 class="error">No Persons found.</h2></div>';
}
get_footer(); ?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment