Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
438 lines (343 sloc) 15 KB
<?php
if( basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME']) )
die();
require_once( dirname(__FILE__).'/lib/agapetry_config_items.php');
class CR_Data_Sources extends AGP_Config_Items {
// optionally, populate with StdObject objects by passing in array of members
function CR_Data_Sources( $arr = '', $action_hook = '' ) {
global $wpdb;
$this->AGP_Config_Items( $arr, $action_hook );
// add default WP taxonomy data source
// note: term_taxonomy must be registered as the source table to support abstract descendant retrieval function.
// code will account for location of name column in related terms table
$args = array(
'is_taxonomy' => 1, 'taxonomy_only' => 1,
'table_basename' => 'term_taxonomy', 'table' => $wpdb->prefix . 'term_taxonomy',
'table_alias' => 'tt',
'cols' => (object) array( 'id' => 'term_id', 'name' => 'name', 'parent' => 'parent' ), // NOTE on ID col: DB queries actually use term_taxonomy_id based on attributes returned by get_terms_query_vars. term_id here is used for categories queries. Possible Todo: resolve this discrepancy and potential bug source
'http_post_vars' => (object) array( 'id' => 'tag_ID' ),
'uri_vars' => (object) array( 'id' => 'tag_ID' )
); // end outer array
// $src_name, $table_basename, $label_singular, $label_name, $col_id, $col_name
$this->add('term', 'role-scoper', __('Term', 'scoper'), __('Terms', 'scoper'), 'terms', 'term_id', 'name', $args );
}
function &add( $name, $defining_module, $label_singular, $label_name, $table_basename, $col_id, $col_name, $args) {
if ( $this->locked ) {
$notice = sprintf('A plugin or theme (%1$s) is too late in its attempt to define a data source (%2$s).', $defining_module, $name)
. '<br /><br />' . 'This must be done via the define_data_sources_rs hook.';
rs_notice($notice);
return;
}
if ( isset($this->members[$name]) )
unset($this->members[$name]);
$this->members[$name] = new CR_Data_Source($name, $defining_module, $label_singular, $label_name, $table_basename, $col_id, $col_name, $args);
$this->process( $this->members[$name] );
return $this->members[$name];
}
// accepts reference to WP_Data_Source object (must pass object so we can call base class function statically)
function process( &$src ) {
global $wpdb;
// apply wp prefix to tablename
if ( ! isset($src->table) && ! empty($src->table_basename) ) { // the prefix was already applied, or is unnecessary
if ( empty($src->table_no_prefix) )
$src->table = $wpdb->prefix . $src->table_basename;
else
$src->table = $src->table_basename;
}
// if no alias specified, set alias property to table name
if ( empty($src->table_alias) )
$src->table_alias = $src->table;
// default object_types array to single member matching source name
if ( empty($src->object_types) ) {
$src->object_types = array( $src->name => (object) array() );
if ( is_admin() ) {
$src->object_types[$src->name]->labels = $src->labels;
}
}
foreach ( array_keys($src->object_types) as $name )
$src->object_types[$name]->name = $name;
}
function get_object($src_name, $object_id, $cols = '') {
// special cases to take advantage of cached post/link
if ( ('post' == $src_name) ) {
if ( $cols && ! strpos( $cols, ',' ) )
return get_post_field( $cols, $object_id, 'raw' );
else
return get_post($object_id);
} elseif ( 'link' == $src_name ) {
return get_bookmark($object_id);
} else {
if ( ! $src = $this->get($src_name) )
return;
global $wpdb;
if ( ! $cols )
$cols = '*';
if ( empty($object_id) )
return array();
return scoper_get_row("SELECT $cols FROM $src->table WHERE {$src->cols->id} = '$object_id' LIMIT 1");
} // end switch
}
function detect($what, $src, $object_id = 0, $object_type = '', $query = '') {
// so we can pass in $src object or $src_name string
if ( ! $src = $this->get($src) )
return;
// if there is only one possible answer, give it
if ( 'id' != $what ) {
if ( ( 'type' == $what ) && ( 'post' == $src->name ) )
return cr_find_post_type();
if ( $it = $this->get_the_only($what, $src) )
return $it;
if ( $it = $this->get_from_func($what, $src) )
return $it;
} else {
if ( defined('XMLRPC_REQUEST') ) {
if ( ! empty( $GLOBALS['xmlrpc_post_id_rs'] ) )
return $GLOBALS['xmlrpc_post_id_rs'];
else {
global $wp_xmlrpc_server;
if ( ! empty( $wp_xmlrpc_server->message->params) ) {
if ( in_array( $wp_xmlrpc_server->message->methodName, array( 'mt.setPostCategories', 'metaWeblog.editPost', 'metaWeblog.getPost' ) ) ) {
if ( ! empty( $wp_xmlrpc_server->message->params[0] ) ) {
return $wp_xmlrpc_server->message->params[0];
}
}
}
return 0;
}
}
if ( 'post' == $src->name && ! empty($GLOBALS['post']) ) {
if ( ! is_object($GLOBALS['post']) )
$GLOBALS['post'] = get_post( $GLOBALS['post'] );
if ( 'auto-draft' == $GLOBALS['post']->post_status )
return 0;
else
return $GLOBALS['post']->ID;
}
}
// Is it set as a $_POST variable?
if ( $it = $this->get_from_http_post($what, $src, $object_type) )
return $it;
/*
// TODO: test this (it would eliminate unnecessary clauses in some queries where object type can be determined)
// Is it one of the query variables in current WP query?
if ( 'post' == $src->name ) {
global $wp_query;
if ( ! empty($wp_query->query) ) {
if ( $it = $this->get_from_queryvars($what, $src, $wp_query->query, $object_type) )
return $it;
}
}
*/
// If we have the object ID, go to the source
if ( $object_id )
if ( $it = $this->get_from_db($what, $src, $object_id) )
return $it;
// Is it one of the query variables in current URI?
if ( $it = $this->get_from_uri($what, $src, $object_type) )
return $it;
// Does the last database query include a helpful equality clause?
if ( $it = $this->get_from_query($what, $src, $query) )
return $it;
// if detection failed and the desired quanity is a member of a config array, default to first array element
if ( $it = $this->get_the_only($what, $src, true) )
return $it;
return ( in_array( $what, array( 'id', 'parent' ) ) ) ? 0 : '';
}
function get_the_only($what, $src, $force_first = false) {
if ( ! $src = $this->get($src) )
return;
if ( isset( $src->collections[$what] ) ) {
$collection_property = $src->collections[$what];
if ( isset( $src->$collection_property ) ) {
// If only one object type is defined, we have a winner.
if ( $force_first || ( 1 == count( $src->$collection_property ) ) ) {
reset( $src->$collection_property );
return key( $src->$collection_property );
}
}
} elseif ( ('type' == $what) && ( ! isset($src->object_types) || ( count($src->object_types) < 2 ) ) )
return $src->name;
}
function get_from_func($what, $src) {
if ( ! $src = $this->get($src) )
return;
if ( ! isset( $src->collections[$what] ) )
return;
$collection_property = $src->collections[$what];
if ( isset( $src->$collection_property ) )
foreach ( $src->$collection_property as $it => $prop )
if ( isset( $prop->function ) )
if ( call_user_func($prop->function) )
return $it;
}
function get_from_db($what, $src, $object_id) {
if ( ! method_exists($this, 'get_object') )
return;
if ( ! $src = $this->get($src) )
return;
if ( ! isset($src->cols->$what) )
return;
$col = $src->cols->$what;
if ( $object = $this->get_object($src->name, $object_id, $col) ) {
if ( is_object( $object ) ) {
if ( isset( $object->$col ) )
return $object->$col;
} else
return $object;
}
}
function get_from_http($what, $src) {
if ( $val = $this->get_from_http_post($what, $src) )
return $val;
if ( $val = $this->get_from_urivars($what, $src) )
return $val;
}
// determines, using cfg->data_sources config, the http POST variable for desired information, then returns its value if present
function get_from_http_post($what, $src, $object_type = '') {
if ( empty($_POST) ) {
if ( defined( 'XMLRPC_REQUEST' ) ) {
if ( ! empty($GLOBALS['scoper_xmlrpc_post_status'] ) ) {
return $GLOBALS['scoper_xmlrpc_post_status'];
}
else {
global $wp_xmlrpc_server;
if ( ! empty( $wp_xmlrpc_server->message->params) ) {
if ( 'metaWeblog.newPost' == $wp_xmlrpc_server->message->methodName ) { // TODO: move to function
return ( ! empty( $wp_xmlrpc_server->message->params[4] ) ) ? 'publish' : 'draft';
}
}
}
}
return;
}
if ( ! $src = $this->get($src) )
return;
/*
rs_errlog('');
rs_errlog("get $what from_http_post");
rs_errlog( serialize($_POST) );
*/
$varname = $this->get_varname('http_post', $what, $src, $object_type);
//rs_errlog('varname: '. $varname);
if ( isset($_POST[$varname]) ) {
return $_POST[$varname];
} else {
if ( isset($src->http_post_vars_alt->$what) ) {
$vars_alt = (array) $src->http_post_vars_alt->$what;
foreach ( $vars_alt as $varname_alt ) {
if ( isset($_POST[$varname_alt]) ) {
return $_POST[$varname_alt];
}
}
}
}
}
// determines, using cfg->data_sources config, the URI query variable for desired information, then returns its value if present
function get_from_uri($what, $src, $object_type = '') {
// workaround for WP 3.0, which uses post.php, edit.php, post-new.php for all post types
if ( ( 'type' == $what ) && ( 'post' == $src->name ) )
return cr_find_post_type();
if ( ! $src = $this->get($src) )
return;
/*
rs_errlog('');
rs_errlog("get $what from_uri");
rs_errlog( 'URI: '. $_SERVER['REQUEST_URI'] );
*/
// Try to pull the desired value from URI variables,
// using data_sources definition to convert the abstract $what into URI variable name
$varname = $this->get_varname('uri', $what, $src, $object_type);
//rs_errlog('varname: '. $varname);
if ( isset($_GET[$varname]) ) {
return $_GET[$varname];
} else {
if ( isset($src->uri_vars_alt->$what) ) {
$vars_alt = (array) $src->uri_vars_alt->$what;
foreach ( $vars_alt as $varname_alt ) {
if ( isset($_GET[$varname_alt]) ) {
return $_GET[$varname_alt];
}
}
}
}
}
function get_from_query($what, $src, $query) {
if ( ! $query )
return;
if ( ! $src = $this->get($src) )
return;
if ( empty($src->cols->$what) )
return;
$col = $src->cols->$what;
// force standard query padding
$query = preg_replace("/$col\s*=\s*'/", "$col = '", $query);
$found = array();
$search = "$col = '";
$pos = -1;
do {
$pos = strpos($query, $search, $pos + 1);
if ( false !== $pos ) {
$startpos = strpos($query, "'", $pos + strlen($search) );
$val = substr($query, $pos + strlen($search), $startpos - $pos - strlen($search) );
$found[$val] = 1;
}
} while ( false !== $pos );
if ( ! $found || ( count($found) > 1 ) )
return; // query contains zero or multiple equality clauses for requested variable (currently not considering IN clauses)
return $val;
}
function get_varname( $var_type, $what_for, $src, $object_type = '') {
if ( ! $src = $this->get($src) )
return;
$vars = "{$var_type}_vars";
// return otype-specific variable, if defined
if ( ! empty($object_type) )
if ( isset($src->object_types[$object_type]->$vars->{$what_for}[CURRENT_ACCESS_NAME_RS] ) )
return $src->object_types[$object_type]->$vars->{$what_for}[CURRENT_ACCESS_NAME_RS];
if ( isset($src->$vars) && is_object($src->$vars) && isset($src->$vars->$what_for) )
return $src->$vars->$what_for;
elseif ( isset($src->cols->$what_for) )
return $src->cols->$what_for;
else
return $what_for;
}
}
// Note: These classes are currently for API support only;
// Internal usage (below) mirrors this interface but instantiates via stdObject cast from array
class CR_Data_Source extends AGP_Config_Item {
var $table_basename; // REQUIRED: database table name, without wp prefix
var $table; // generated from table_basename
var $table_alias = ''; // database table alias, if any, for use in queries
//var $display_name; // use labels->singular_name instead
//var $display_name_plural = '';// use labels->name instead
var $cols; // database column names. required keys: id, name, content
// optional keys: type, owner, parent, status, excerpt
var $http_post_vars = array(); // http_post_vars[agp_key] = POST variable name for data indicated by agp_key, if it differs from cols[agp_key]
var $uri_vars = array(); // uri_vars[agp_key] = URI variable name for data indicated by agp_key, if it differs from cols[agp_key]
var $uri_vars_alt; // (object) array( 'id' => array('post_id') )
var $http_post_vars_alt; // (object) array( 'id' => array('post_id') )
var $object_types = array(); // array[obj type name] = various optional properties for object types included in this data source
// (if not set, default to single object type with same name as source)
// valid props:
// object_types[obj type name]->uri_vars = array of otype-specific uri query variable names for source id : array( 'id' => array( 'front' => 'page_id' ) )
// ->uri = array of uri substrings which indicate this object type
var $statuses = array(); // statuses = array[access_name] = array( status_name => status_type_val )
// (indicates statuses valid for display in the specified access type, and the values representing them in DB record and POST vars)
var $collections = array(); // collections[ agp_key ] = property name, indicating array property
// ( i.e. collections['type'] = 'object_types' relates cols->type to object_types[object type name] )
var $is_taxonomy = 0; // This data source stores taxonomy terms (may be WP core "taxonomy" or other)
var $taxonomy_only = 0; // This data source is significant only as a taxonomy for other data sources
var $uses_taxonomies = array();
var $query_hooks; // (object) array( 'request' => 'posts_request', 'results' => 'posts_results', 'listing' => 'the_posts' ),
var $query_replacements = array();
var $no_object_roles = 0;
var $edit_url = ''; // URL to object editor, includes [id] placeholder
function CR_Data_Source( $name, $defining_module, $label_singular, $label_name, $table_basename, $col_id, $col_name, $args = array() ) {
$this->cols = (object) array( 'id' => $col_id, 'name' => $col_name );
$this->AGP_Config_Item($name, $defining_module, $args);
$this->labels->name = $label_name;
$this->labels->singular_name = $label_singular;
$this->table_basename = $table_basename;
}
}
?>