Skip to content

Instantly share code, notes, and snippets.

@jonathonbyrdziak
Created September 21, 2011 15:30
Show Gist options
  • Save jonathonbyrdziak/1232377 to your computer and use it in GitHub Desktop.
Save jonathonbyrdziak/1232377 to your computer and use it in GitHub Desktop.
Relationship API
<?php
/**
* @Author Anonymous
* @link http://www.redrokk.com
* @Package Wordpress
* @SubPackage Relationships
*
* @version 2.0
*/
//security
defined('ABSPATH') or die('You\'re not supposed to be here.');
/**
*
*
* @author Anonymous
* @example
$gallery = redrokk_relationship_class::getInstance('gallery');
*/
if (!class_exists('redrokk_relationship_class')):
class redrokk_relationship_class
{
/**
*
* @var string
*/
protected $id;
/**
* The different kinds of relationships that you can create with this system
*
* one-to-one
* one-to-many
* many-to-many
*
* @var string
*/
protected $type = 'many-to-many';
/**
* post | taxonomy | user | comment
*
* @var string
*/
protected $left_type = false;
/**
* clt name | term | comment | user
*
* @var string
*/
protected $left = 'post';
/**
*
* @var string
*/
protected $right_type = false;
/**
*
* @var string
*/
protected $right = 'post';
/**
*
* @var string
*/
protected $_table = 'relationships';
/**
* Needs to be changed if the database table is ever changed.
*
* @var string
*/
protected $_ver = '0.1';
/**
*
* @var string
*/
protected $_class;
/**
* Constructor.
*
*/
function __construct( $options = array() )
{
// initializing
$this->setProperties($options);
// processing
$this->update_check();
$this->trigger_action();
// hooks and filters
add_filter( 'init', array($this, 'validate'), 50 );
add_action( 'admin_init', array($this, 'init_metaboxes') );
add_action( 'admin_head', array($this, 'css') );
add_action( 'current_screen', array($this, 'init_user_metabox') );
// @TODO create the query filter part
//add_action( 'restrict_manage_posts', array($this, 'create_filter') );
}
/**
*
*/
function setUnLinkRecord()
{
// initializing
$direction = $_REQUEST['relationship_direction'];
$left = $direction=='left' ?$_REQUEST['relationship_id'] :$_REQUEST['relationship_oid'];
$right = $direction=='left' ?$_REQUEST['relationship_oid'] :$_REQUEST['relationship_id'];
$this->setUnAssociation( $this->getObject( $left ), $this->getObject( $right, 'right' ) );
}
/**
* When one record exists and another is just being created
*
* @param int $post_id
*/
function setLinkNewRecord( $post_id )
{
// initializing
$direction = $_REQUEST['relationship_direction'];
$left = $direction=='left' ?$post_id :$_REQUEST['relationship_id'];
$right = $direction=='left' ?$_REQUEST['relationship_id'] :$post_id;
$left_o = $this->getObject( $left );
$right_o = $this->getObject( $right, 'right' );
if ($this->areRelated($left_o, $right_o)) return;
$this->setAssociation( $left_o, $right_o );
}
/**
* When both records already exist
*
*/
function setLinkExistingRecord()
{
// initializing
$direction = $_REQUEST['relationship_direction'];
$left = $direction=='left' ?$_REQUEST['relationship_id'] :$_REQUEST['relationship_oid'];
$right = $direction=='left' ?$_REQUEST['relationship_oid'] :$_REQUEST['relationship_id'];
$left_o = $this->getObject( $left );
$right_o = $this->getObject( $right, 'right' );
if ($this->areRelated($left_o, $right_o)) return;
$this->setAssociation( $left_o, $right_o );
}
/**
*
* @param object $obj1
* @param object $obj2
*/
function setAssociation( $obj1, $obj2 )
{
// initializing
global $wpdb;
if ($this->getDirection( $obj1 ) == 'left') {
$left_id = $this->getObjectID( $obj1 );
$right_id = $this->getObjectID( $obj2 );
} else {
$left_id = $this->getObjectID( $obj2 );
$right_id = $this->getObjectID( $obj1 );
}
$query = "INSERT INTO `".$wpdb->prefix.$this->_table."` "
."( `left_object_type`, `left_object`, `left_id`, `right_object_type`, `right_object`, `right_id` ) VALUES"
."( '".$this->left_type."', '".$this->left."', '".$left_id."',"
."'".$this->right_type."', '".$this->right."', '".$right_id."' );";
return $wpdb->query( $query );
}
/**
*
* @param object $o
*/
function getDirection( $o )
{
if ($this->left_type == $this->getObjectType( $o ) && $this->left == $this->getObjectName( $o )) {
return 'left';
}
return 'right';
}
/**
*
* @param object $obj1
* @param object $obj2
*/
function setUnAssociation( $obj1, $obj2 )
{
// initializing
global $wpdb;
if ($this->getDirection( $obj1 ) == 'left') {
$left_id = $this->getObjectID( $obj1 );
$right_id = $this->getObjectID( $obj2 );
} else {
$left_id = $this->getObjectID( $obj2 );
$right_id = $this->getObjectID( $obj1 );
}
$query = "DELETE FROM `".$wpdb->prefix.$this->_table."` "
. " WHERE ("
. " `left_object_type` = '$this->left_type' "
. " AND `left_object` = '$this->left' "
. " AND `left_id` = '$left_id' "
. " AND `right_object_type` = '$this->right_type' "
. " AND `right_object` = '$this->right' "
. " AND `right_id` = '$right_id' "
. ") OR ("
. " `left_object_type` = '$this->right_type' "
. " AND `left_object` = '$this->right' "
. " AND `left_id` = '$right_id' "
. " AND `right_object_type` = '$this->left_type' "
. " AND `right_object` = '$this->left' "
. " AND `right_id` = '$left_id' "
. ")";
$results = $wpdb->query( $query );
return $results;
}
/**
*
* @param unknown_type $o
*/
function areRelated( $o, $o1 )
{
global $wpdb;
$id = $this->getObjectID($o);
$type = $this->getObjectType($o);
$object = $this->getObjectName($o);
$id1 = $this->getObjectID($o1);
$type1 = $this->getObjectType($o1);
$object1 = $this->getObjectName($o1);
$q = "SELECT * FROM `{$wpdb->prefix}".$this->_table."` WHERE "
."( `left_object_type` = '$type' AND `left_object` = '$object' AND `left_id` = '$id' "
." AND `right_object_type` = '$type1' AND `right_object` = '$object1' AND `right_id` = '$id1' )"
."OR"
."( `right_object_type` = '$type' AND `right_object` = '$object' AND `right_id` = '$id' "
." AND `left_object_type` = '$type1' AND `left_object` = '$object1' AND `left_id` = '$id1' )";
// requirements
if (!$results = $wpdb->get_results( $q )) return false;
return true;
}
/**
* Method returns all of the linked objects
*
* @param object|int $o
*/
function getRelated( $o )
{
// initializing
global $wpdb;
$objects = array();
$id = $this->getObjectID($o);
$type = $this->getObjectType($o);
$object = $this->getObjectName($o);
$direction = $this->getDirection($o);
$opposite = $direction == 'left' ?'right' :'left';
if ($direction == 'left') {
$q = "SELECT `right_id` as `id` FROM `{$wpdb->prefix}".$this->_table."` WHERE "
."( `left_object_type` = '$type' AND `left_object` = '$object' AND `left_id` = '$id' "
."AND "
." `right_object_type` = '{$this->right_type}' AND `right_object` = '{$this->right}' )";
} else {
$q = "SELECT `left_id` as `id` FROM `{$wpdb->prefix}".$this->_table."` WHERE "
."( `right_object_type` = '$type' AND `right_object` = '$object' AND `right_id` = '$id' "
."AND "
." `left_object_type` = '{$this->left_type}' AND `left_object` = '{$this->left}' )";
}
// requirements
if (!$results = $wpdb->get_results( $q )) return false;
foreach ((array)$results as $result)
{
$object = $this->getObject( $result->id, $opposite );
if (!$object) continue;
if (!$this->getObjectID( $object )) continue;
$objects[] = $object;
}
if (empty($objects))
return false;
return $objects;
}
/**
* Adds the columns
*
* @param $columns
*/
function create_columns( $columns )
{
// initializing
global $post;
$opposite = $_REQUEST['relationship_direction'] == 'left' ?'right' :'left';
$type = $opposite.'_type';
if (get_role( $this->$opposite ) !== null
|| taxonomy_exists( $this->$opposite )) {
$name = ucwords($this->$opposite);
} elseif (post_type_exists( $this->$opposite )) {
$postType = get_post_type_object($this->$type);
$name = $postType->labels->name;
}
$newColumns = array('cb' => $columns['cb'] );
$newColumns['relationship_button'] = 'Actions';
$newColumns = $newColumns + $columns;
$newColumns['relationship_association'] = $name.' Association';
if (array_key_exists('author', $columns))
{
$tmp = $newColumns['author'];
unset($newColumns['author']);
$newColumns['author'] = $tmp;
}
if (array_key_exists('date', $columns))
{
$tmp = $newColumns['date'];
unset($newColumns['date']);
$newColumns['date'] = $tmp;
}
return $newColumns;
}
/**
*
*
* @param string $column_id
* @return boolean
*/
function table_user_columns( $empty = '', $column_id, $oid )
{
ob_start();
// initializing
global $post;
$direction = $_REQUEST['relationship_direction'];
$opposite = $direction == 'left' ?'right' :'left';
$id = $_REQUEST['relationship_id'];
switch ($column_id) {
case 'relationship_button':
echo '<a class="preview button" href="'.$this->get_link('link', $opposite, $id, $oid).'">Link Record</a>';
break;
case 'relationship_association':
$children = $this->getObject( $oid, $direction );
//@TODO show a csv list of related items
break;
}
return ob_get_clean();
}
/**
*
*
* @param string $column_id
* @return boolean
*/
function table_columns( $column_id )
{
// initializing
global $post;
$direction = $_REQUEST['relationship_direction'];
$opposite = $direction == 'left' ?'right' :'left';
$id = $_REQUEST['relationship_id'];
switch ($column_id) {
case 'relationship_button':
echo '<a class="preview button" href="'.$this->get_link('link', $opposite, $id, $post->ID).'">Link Record</a>';
break;
case 'relationship_association':
$children = $this->getRelated( $post );
//@TODO show a csv list of related items
break;
}
}
/**
* Method displays the css
*
*/
function css()
{
?>
<style type="text/css">
#<?php echo $this->id; ?> table.relationship_table th,
#<?php echo $this->id; ?> table.relationship_table td { text-align:left;margin:0;padding:0; }
#<?php echo $this->id; ?> table.relationship_table th,
#<?php echo $this->id; ?> table.relationship_table { margin:0;padding:0;border-spacing: 0; }
#<?php echo $this->id; ?> .autogenerated-metabox {margin:0px;}
#<?php echo $this->id; ?> .autogenerated-metabox td {padding:0px;}
#<?php echo $this->id; ?> .inside {margin:0 0 30px;}
#<?php echo $this->id; ?> .thead {background:#DFDFDF url(<?php bloginfo('url'); ?>/wp-admin/images/gray-grad.png) 0 0 repeat-x;line-height:20px;}
#<?php echo $this->id; ?> .thead th {padding:5px !important;width:200px;}
#<?php echo $this->id; ?> .relationship_table td {padding:3px !important;}
#<?php echo $this->id; ?> .relationship_actions {width:50px !important;}
#<?php echo $this->id; ?> table.relationship_table td {border-bottom:1px solid #eee;padding-bottom:20px;margin-bottom:10px;}
#<?php echo $this->id; ?> table.relationship_table {width: 100%;border-bottom:1px solid #ccc;padding-bottom:20px;margin-bottom:10px;}
#<?php echo $this->id; ?> #<?php echo $this->id; ?>-table-ID {width:50px !important;}
#<?php echo $this->id; ?> h3.hndle {background-color: #636363;background-image: url(<?php bloginfo('url'); ?>/wp-admin/images/fav.png);border-color: #636363;color: white;text-shadow: #3F3F3F 0px -1px 0px;}
#<?php echo $this->id; ?>:hover .handlediv {cursor:pointer;background: transparent url(<?php bloginfo('url'); ?>/wp-admin/images/widgets-arrow.gif) no-repeat scroll 0px -1px;}
#relationship_button { width:85px; }
</style>
<?php
}
/**
* Method creates a filter select input
*
*/
function create_filter()
{
$opposite = $_REQUEST['relationship_direction'] == 'left' ?'right' :'left';
?>
<label>
<input type="checkbox" name="relationship_filter" value="<?php echo $opposite ?>" />
Filter by <?php echo ucwords($this->$opposite) ?> Associations
</label>
<input type="hidden" name="redrokk_relationship_class" value="<?php echo $this->id ?>" />
<input type="hidden" name="relationship_id" value="<?php echo $_REQUEST['relationship_id'] ?>" />
<input type="hidden" name="relationship_action" value="<?php echo $_REQUEST['relationship_action'] ?>" />
<input type="hidden" name="relationship_direction" value="<?php echo $_REQUEST['relationship_direction'] ?>" />
<?php
}
/**
*
*/
function init_metaboxes()
{
// Add the left metabox
if ($this->get_current_type() == $this->right) {
add_meta_box(
$this->id,
'Related '.ucwords($this->left),
array($this, 'metabox'),
$this->right,
'normal',
'default',
'left'
);
}
// Add the right metabox
elseif ($this->get_current_type() == $this->left) {
add_meta_box(
$this->id,
'Related '.ucwords($this->right),
array($this, 'metabox'),
$this->left,
'normal',
'default',
'right'
);
}
}
/**
* The related node listings on the users page
*
*/
function metabox_user( $user )
{
//initializing
$direction = $this->getDirection( $user );
$params = array();
$opposite = $params['args'] = $direction == 'left' ?'right' :'left';
$property = $opposite.'_type';
$p = $this->$property;
?>
<h3>Related <?php echo ucwords($p) ?></h3>
<div id="<?php echo $this->id ?>">
<?php $this->metabox( $user, $params ); ?>
</div>
<?php
}
/**
* The related bode listings
*
*/
function metabox( $current, $params = array() )
{
//initializing
$direction = $params['args'];
$opposite = $direction == 'left' ?'right' :'left';
$children = $this->getRelated( $current );
$columns = array(
'post' => array('post_title' => 'Title','post_type' => 'Post Type', 'post_status' => 'Status'),
'user' => array('display_name' => 'User', 'user_email' => 'Email', 'role' => 'Role','user_status' => 'Status' )
);
?>
<a name="<?php echo $this->id; ?>"></a>
<?php if (!is_array($children)): ?>
<p>There are no relationships at this time.
<a class="preview button" href="<?php echo $this->get_link('new', $direction, $current->ID); ?>">New Record</a>
<a style="margin-right:10px;" class="preview button" href="<?php echo $this->get_link('existing', $direction, $current->ID); ?>">Link Record</a>
</p>
<?php else:
// Getting the headers
$type = $this->getObjectType( $children[0] );
$columns = apply_filters("{$this->id}-$direction-headers", $columns[$type]);
?>
<table class="relationship_table">
<tr class="thead">
<?php foreach ($columns as $property => $title): ?>
<th class="<?php echo $this->id; ?>-<?php echo $property; ?>">
<?php echo $title; ?>
</th>
<?php endforeach; ?>
<th class="relationship_actions">Actions</th>
</tr>
<?php foreach ($children as $child): ?>
<tr>
<?php foreach ($columns as $property => $title): ?>
<td>
<?php
switch ($property)
{
default: echo $child->$property; break;
case 'display_name':
echo '<a href="'. admin_url('user-edit.php?user_id='.$child->ID) .'">'.
$child->$property.'</a>';
break;
case 'post_title':
echo '<a href="'. admin_url('post.php?post='.$child->ID.'&action=edit') .'">'.
$child->$property.'</a>';
break;
case 'post_date':
echo date('M jS Y', strtotime($child->$property));
break;
case 'role':
echo $child->roles[0];
break;
}
?>
</td>
<?php endforeach; ?>
<td>
<a class="preview button" href="<?php echo $this->get_link('unlink', $opposite, $current->ID, $child->ID); ?>">Unlink</a>
</td>
</tr>
<?php endforeach; ?>
</table>
<div style="margin-right:20px;">
<a class="preview button" href="<?php echo $this->get_link('new', $direction, $current->ID); ?>">New Record</a>
<a style="margin-right:10px;" class="preview button" href="<?php echo $this->get_link('existing', $direction, $current->ID); ?>">Link Record</a>
</div>
<div style="width:100%;display:block;clear:both;"></div>
<?php endif;
}
/**
* Echo new relationship link
*
* Function is responsible for creating this link and echoing it
*
*
*/
function get_link( $action = 'new', $direction = 'left', $lid = false, $rid = false )
{
$args = array(
'redrokk_relationship_class'=> $this->id,
'relationship_action' => $action,
'relationship_direction' => $direction
);
if ($lid) {
$args['relationship_id'] = $lid;
}
if ($rid) {
$args['relationship_oid'] = $rid;
}
switch ($action.'_'.$this->getType( $direction ))
{
// Creating new nodes from metabox
default:
case 'new_post':
$href = admin_url('post-new.php?post_type='.$this->$direction);
break;
case 'new_user':
$href = admin_url('user-new.php');
break;
// Existing nodes from metabox to open listing
case 'existing_post':
$href = admin_url('edit.php?post_type='.$this->$direction);
break;
case 'existing_user':
$href = admin_url('users.php');
break;
// Unlinking a relationship from metabox and listing
case 'unlink_post':
$href = admin_url('post.php?action=edit&post='.$lid);
break;
case 'unlink_user':
$href = admin_url('user-edit.php?user_id='.$lid);
break;
// linking a new relationship from listing
case 'link_post':
$href = admin_url('post.php?action=edit&post='.$lid);
break;
case 'link_user':
$href = admin_url('user-edit.php?user_id='.$lid);
break;
}
return add_query_arg($args, $href);
}
/**
* Method sets catches the requested actions and processes any new hooks for those actions.
*
*/
function trigger_action()
{
// requirements
if (!array_key_exists('redrokk_relationship_class', $_REQUEST)) return false;
if (!array_key_exists('relationship_action', $_REQUEST)) return false;
if ($_REQUEST['redrokk_relationship_class'] !== $this->id) return false;
// initializing
$direction = $_REQUEST['relationship_direction'];
$opposite = $direction == 'left' ?'right' :'left';
// hooks and filters
switch ($_REQUEST['relationship_action']) {
default:
case 'existing':
add_filter( "manage_edit-{$this->$direction}_columns", array($this, 'create_columns'), 10, 1);
add_filter( 'manage_users_columns', array($this, 'create_columns'), 10, 1);
add_action( 'manage_users_custom_column', array($this, 'table_user_columns'), 20, 3 );
add_action( 'manage_posts_custom_column', array($this, 'table_columns'), 20, 1 );
add_action( 'manage_pages_custom_column', array($this, 'table_columns'), 20, 1 );
break;
case 'link':
add_action( 'init', array($this, 'setLinkExistingRecord'), 60 );
break;
case 'unlink':
add_action( 'init', array($this, 'setUnLinkRecord'), 60 );
break;
// creating
case 'new':
add_action( 'dbx_post_sidebar', array($this, 'doNewActionInputs'), 100 );
break;
case 'new-saved':
add_action( 'save_post', array($this, 'setLinkNewRecord'), 60 );
break;
}
}
/**
*
* @return unknown
*/
function get_current_type()
{
if (isset($_GET['post'])) {
return get_post_type( get_post($_GET['post']) );
}
}
/**
*
*/
function init_user_metabox()
{
if ( get_current_screen() === NULL ) return false;
if ( get_current_screen()->base !== 'user-edit' ) return false;
add_action( 'edit_user_profile', array($this, 'metabox_user') );
}
/**
*
*/
function doNewActionInputs()
{
?>
<input type="hidden" name="redrokk_relationship_class" value="<?php echo $this->id ?>" />
<input type="hidden" name="relationship_id" value="<?php echo $_REQUEST['relationship_id'] ?>" />
<input type="hidden" name="relationship_action" value="new-saved" />
<input type="hidden" name="relationship_direction" value="<?php echo $_REQUEST['relationship_direction'] ?>" />
<?php
}
/**
*
* @param object $o
*/
function getObjectType( $o )
{
if (isset( $o->term_id )) {
return 'taxonomy';
} elseif (isset( $o->post_type )) {
return 'post';
} elseif (is_a($o, 'WP_User')) {
return 'user';
}
}
/**
*
* @param object $o
*/
function getObjectName( $o )
{
switch ($this->getObjectType( $o ))
{
default:
case 'post':
return $o->post_type;
break;
case 'user':
return 'user';
break;
case 'taxonomy':
// @todo return taxonomy name or term name?
break;
}
}
/**
*
* @param unknown_type $direction
*/
function getType( $direction = 'left' )
{
$type = $direction.'_type';
return $this->$type;
}
/**
*
* @param unknown_type $id
* @param unknown_type $direction
*/
function getObject( $id, $direction = 'left' )
{
switch($this->getType( $direction ))
{
default:
case 'post':
return get_post( $id );
break;
case 'user':
return new WP_User( $id );
break;
case 'taxonomy':
return get_term( $id, $this->$direction, ARRAY_A );
break;
}
return false;
}
/**
*
* @param unknown_type $o
*/
function getObjectID( $o )
{
if (isset( $o->ID )) {
return $o->ID;
} elseif (isset( $o->term_id )) {
return $o->term_id;
}
}
/**
* Runs any final validation before we get to work
*
*/
function validate()
{
// set the proper objects
if (is_wp_error( $e = $this->setType( ) )) {
// @TODO do error display
}
if (is_wp_error( $e = $this->setType( 'right' ) )) {
// @TODO do error display
}
}
/**
* Method makes sure that the objects are set properly
*
* @param string $direction
* @return WP_Error|boolean
*/
function setType( $direction = 'left' )
{
// initializing
$property = $direction.'_type';
if (!$this->$property) {
if (get_role( $this->$direction ) || $this->$direction == 'user') {
$this->$property = 'user';
} elseif (taxonomy_exists( $this->$direction )) {
$this->$property = 'taxonomy';
} elseif (post_type_exists( $this->$direction )) {
$this->$property = 'post';
} else {
return new WP_Error('broke', __("redrokk_relationship_class : Bad Configuration, the $direction object type is unknown."));
}
}
return true;
}
/**
* Method makes sure that the table is up to date for this class
*
*/
function update_check()
{
if (get_site_option('redrokk_relationship_class::_ver') == $this->_ver)
return true;
return $this->create_table();
}
/**
* Creates `relationship` table if it doesn't exist
*
*/
function create_table()
{
// initializing
global $wpdb;
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
if (!empty ($wpdb->charset))
$charset_collate = "DEFAULT CHARACTER SET {$wpdb->charset}";
if (!empty ($wpdb->collate))
$charset_collate .= " COLLATE {$wpdb->collate}";
// creating the table
$sql = "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}{$this->_table}` (
id int(11) NOT NULL AUTO_INCREMENT,
left_object_type varchar(32) NOT NULL,
left_object varchar(32) NOT NULL,
left_id int(11) NOT NULL,
right_object_type varchar(32) NOT NULL,
right_object varchar(32) NOT NULL,
right_id int(11) NOT NULL,
UNIQUE KEY id (id)
) {$charset_collate};";
$wpdb->query($sql);
update_option( "redrokk_relationship_class::_ver", $this->_ver );
return true;
}
/**
*
* @return string
*/
function get_current_url()
{
return 'http'.((!empty($_SERVER['HTTPS']))?'s':'').'://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
}
/**
* Method to bind an associative array or object to the JTable instance.This
* method only binds properties that are publicly accessible and optionally
* takes an array of properties to ignore when binding.
*
* @param mixed $src An associative array or object to bind to the JTable instance.
* @param mixed $ignore An optional array or space separated list of properties to ignore while binding.
*
* @return boolean True on success.
*
* @link http://docs.joomla.org/JTable/bind
* @since 11.1
*/
public function bind($src, $ignore = array())
{
// If the source value is not an array or object return false.
if (!is_object($src) && !is_array($src))
{
trigger_error('Bind failed as the provided source is not an array.');
return false;
}
// If the source value is an object, get its accessible properties.
if (is_object($src))
{
$src = get_object_vars($src);
}
// If the ignore value is a string, explode it over spaces.
if (!is_array($ignore))
{
$ignore = explode(' ', $ignore);
}
// Bind the source value, excluding the ignored fields.
foreach ($this->getProperties() as $k => $v)
{
// Only process fields not in the ignore array.
if (!in_array($k, $ignore))
{
if (isset($src[$k]))
{
$this->$k = $src[$k];
}
}
}
return true;
}
/**
* Set the object properties based on a named array/hash.
*
* @param mixed $properties Either an associative array or another object.
*
* @return boolean
*
* @since 11.1
*
* @see set()
*/
public function setProperties($properties)
{
if (is_array($properties) || is_object($properties))
{
foreach ((array) $properties as $k => $v)
{
// Use the set function which might be overridden.
$this->set($k, $v);
}
return true;
}
return false;
}
/**
* Modifies a property of the object, creating it if it does not already exist.
*
* @param string $property The name of the property.
* @param mixed $value The value of the property to set.
*
* @return mixed Previous value of the property.
*
* @since 11.1
*/
public function set($property, $value = null)
{
$_property = 'set'.str_replace(' ', '', ucwords(str_replace('_', ' ', $property)));
if (method_exists($this, $_property)) {
return $this->$_property($value);
}
$previous = isset($this->$property) ? $this->$property : null;
$this->$property = $value;
return $previous;
}
/**
* Returns an associative array of object properties.
*
* @param boolean $public If true, returns only the public properties.
*
* @return array
*
* @see get()
*/
public function getProperties($public = true)
{
$vars = get_object_vars($this);
if ($public)
{
foreach ($vars as $key => $value)
{
if ('_' == substr($key, 0, 1))
{
unset($vars[$key]);
}
}
}
return $vars;
}
/**
* Method returns the called class
*
*/
public static function get_called_class()
{
if (function_exists('get_called_class')) {
return get_called_class();
}
$called_class = false;
$objects = array();
$traces = debug_backtrace();
foreach ($traces as $trace)
{
if (isset($trace['object'])) {
if (is_object($trace['object'])) {
$objects[] = $trace['object'];
}
}
}
if (count($objects)) {
$called_class = get_class($objects[0]);
}
return $called_class;
}
/**
*
* contains the current instance of this class
* @var object
*/
static $_instances = null;
/**
* Method is called when we need to instantiate this class
*
* @param array $options
*/
public static function getInstance( $id, $options = array() )
{
if (!isset(self::$_instances[$id]))
{
$class = self::get_called_class();
$options['_class'] = $class;
$options['id'] = $id;
self::$_instances[$id] =& new $class($options);
}
return self::$_instances[$id];
}
}
endif;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment