/** * Create instance from mixed query vars; also returns the modified query vars. * * @param array Query vars to collect parameters from * @return: * - null means ignore current query * - WP_Error instance if the query is invalid * - array( P2P_Query, array ) */ public static function create_from_qv($q, $object_type) { $q = self::expand_shortcuts($q); if (!isset($q['connected_type'])) { if (isset($q['connected_items'])) { return new WP_Error('no_connection_type', "Queries without 'connected_type' are no longer supported."); } return; } if (isset($q['connected_direction'])) { $directions = (array) _p2p_pluck($q, 'connected_direction'); } else { $directions = array(); } $item = isset($q['connected_items']) ? $q['connected_items'] : 'any'; $ctypes = (array) _p2p_pluck($q, 'connected_type'); $p2p_types = self::expand_ctypes($item, $directions, $object_type, $ctypes); if (empty($p2p_types)) { return new WP_Error('no_direction', "Could not find direction(s)."); } if (1 == count($p2p_types)) { $q = self::finalize_query_vars($q, $p2p_types[0], $item); } $p2p_q = new P2P_Query(); $p2p_q->ctypes = $p2p_types; $p2p_q->items = $item; foreach (array('meta', 'orderby', 'order_num', 'order') as $key) { $p2p_q->{$key} = isset($q["connected_{$key}"]) ? $q["connected_{$key}"] : false; } $p2p_q->query = isset($q['connected_query']) ? $q['connected_query'] : array(); return array($p2p_q, $q); }
/** * Register a connection between two post types. * * This creates the appropriate meta box in the admin edit screen. * * Takes the following parameters, as an associative array: * * - 'name' - string A unique identifier for this connection type. * * - 'from' - string|array The first end of the connection. * * - 'from_query_vars' - array Additional query vars to pass to WP_Query. Default: none. * * - 'to' - string|array The second end of the connection. * * - 'to_query_vars' - array Additional query vars to pass to WP_Query. Default: none. * * - 'fields' - array( key => Title ) Metadata fields editable by the user. Default: none. * * - 'cardinality' - string How many connection can each post have: 'one-to-many', 'many-to-one' or 'many-to-many'. Default: 'many-to-many' * * - 'duplicate_connections' - bool Whether to allow more than one connection between the same two posts. Default: false. * * - 'self_connections' - bool Whether to allow a post to connect to itself. Default: false. * * - 'sortable' - bool|string Whether to allow connections to be ordered via drag-and-drop. Can be 'from', 'to', 'any' or false. Default: false. * * - 'title' - string|array The box's title. Default: 'Connected {$post_type}s' * * - 'from_labels' - array Additional labels for the admin box (optional) * * - 'to_labels' - array Additional labels for the admin box (optional) * * - 'reciprocal' - bool For indeterminate connections: True means all connections are displayed in a single box. False means 'from' connections are shown in one box and 'to' connections are shown in another box. Default: false. * * - 'admin_box' - bool|string|array Whether and where to show the admin connections box. * * - 'can_create_post' - bool Whether to allow post creation via the connection box. Default: true. * * @param array $args * * @return bool|object False on failure, P2P_Connection_Type instance on success. */ function p2p_register_connection_type($args) { if (!did_action('init')) { trigger_error("Connection types should not be registered before the 'init' hook."); } $argv = func_get_args(); if (count($argv) > 1) { $args = array(); foreach (array('from', 'to', 'reciprocal') as $i => $key) { if (isset($argv[$i])) { $args[$key] = $argv[$i]; } } } else { $args = $argv[0]; } if (isset($args['id'])) { $args['name'] = _p2p_pluck($args, 'id'); } if (isset($args['prevent_duplicates'])) { $args['duplicate_connections'] = !$args['prevent_duplicates']; } if (isset($args['show_ui'])) { $args['admin_box'] = array('show' => _p2p_pluck($args, 'show_ui')); if (isset($args['context'])) { $args['admin_box']['context'] = _p2p_pluck($args, 'context'); } } $ctype = P2P_Connection_Type_Factory::register($args); do_action('p2p_registered_connection_type', $ctype, $args); return $ctype; }
function expand_connected_type(&$q) { if (!isset($q['connected_type'])) { return; } $ctype = p2p_type(_p2p_pluck($q, 'connected_type')); if (!$ctype) { return false; } if (isset($q['connected_direction'])) { $directed = $ctype->set_direction(_p2p_pluck($q, 'connected_direction')); } else { if ('any' == $q['connected_items']) { $post_type = isset($q['post_type']) ? $q['post_type'] : 'post'; } else { $post_type = $q['connected_items']; } $directed = P2P_Query::find_direction($ctype, $post_type, 'post'); } if (!$directed) { trigger_error("Can't determine direction", E_USER_WARNING); return false; } $q = $directed->get_connected_args($q); return true; }
/** * Create instance from mixed query vars * * @param array Query vars to collect parameters from * @return: * - null means ignore current query * - WP_Error instance if the query is invalid * - P2P_Query instance on success */ public static function create_from_qv(&$q, $object_type) { $shortcuts = array('connected' => 'any', 'connected_to' => 'to', 'connected_from' => 'from'); foreach ($shortcuts as $key => $direction) { if (!empty($q[$key])) { $q['connected_items'] = _p2p_pluck($q, $key); $q['connected_direction'] = $direction; } } if (!isset($q['connected_type'])) { if (isset($q['connected_items'])) { return new WP_Error('no_connection_type', "Queries without 'connected_type' are no longer supported."); } return; } $ctypes = (array) _p2p_pluck($q, 'connected_type'); if (isset($q['connected_direction'])) { $directions = (array) _p2p_pluck($q, 'connected_direction'); } else { $directions = array(); } $item = isset($q['connected_items']) ? $q['connected_items'] : 'any'; $p2p_types = array(); foreach ($ctypes as $i => $p2p_type) { $ctype = p2p_type($p2p_type); if (!$ctype) { continue; } if (isset($directions[$i])) { $directed = $ctype->set_direction($directions[$i]); } else { $directed = $ctype->find_direction($item, true, $object_type); } if (!$directed) { continue; } $p2p_types[] = $directed; } if (empty($p2p_types)) { return new WP_Error('no_direction', "Could not find direction(s)."); } if (1 == count($p2p_types)) { $directed = $p2p_types[0]; if ($orderby_key = $directed->get_orderby_key()) { $q = wp_parse_args($q, array('connected_orderby' => $orderby_key, 'connected_order' => 'ASC', 'connected_order_num' => true)); } $q = array_merge_recursive($q, array('connected_meta' => $directed->data)); $q = $directed->get_final_qv($q, 'opposite'); $q = apply_filters('p2p_connected_args', $q, $directed, $item); } $p2p_q = new P2P_Query(); $p2p_q->ctypes = $p2p_types; $p2p_q->items = $item; foreach (array('meta', 'orderby', 'order_num', 'order') as $key) { $p2p_q->{$key} = isset($q["connected_{$key}"]) ? $q["connected_{$key}"] : false; } $p2p_q->query = isset($q['connected_query']) ? $q['connected_query'] : array(); return $p2p_q; }
function translate_qv($qv) { $map = array('include' => 'post__in', 'exclude' => 'post__not_in', 'search' => 's', 'page' => 'paged', 'per_page' => 'posts_per_page'); foreach ($map as $old => $new) { if (isset($qv["p2p:{$old}"])) { $qv[$new] = _p2p_pluck($qv, "p2p:{$old}"); } } return $qv; }
function expand_shortcut_qv(&$q) { $qv_map = array('connected' => 'any', 'connected_to' => 'to', 'connected_from' => 'from'); foreach ($qv_map as $key => $direction) { if (!empty($q[$key])) { $q['connected_items'] = _p2p_pluck($q, $key); $q['connected_direction'] = $direction; } } }
private static function expand_shortcuts($q) { $shortcuts = array('connected' => 'any', 'connected_to' => 'to', 'connected_from' => 'from'); foreach ($shortcuts as $key => $direction) { if (!empty($q[$key])) { $q['connected_items'] = _p2p_pluck($q, $key); $q['connected_direction'] = $direction; } } return $q; }
function expand_arg($args) { $box_args = parent::expand_arg($args); foreach (array('can_create_post') as $key) { if (isset($args[$key])) { $box_args[$key] = _p2p_pluck($args, $key); } } $box_args = wp_parse_args($box_args, array('context' => 'side', 'priority' => 'default', 'can_create_post' => true)); return $box_args; }
private function set_labels(&$args) { foreach (array('from', 'to') as $key) { $labels = _p2p_pluck($args, $key . '_labels'); if (empty($labels)) { $labels = $this->side[$key]->get_labels(); } else { $labels = (object) $labels; } $this->labels[$key] = $labels; } }
function filter_ctypes($ctype, $args) { if (isset($args['admin_column'])) { $column_args = _p2p_pluck($args, 'admin_column'); if (!is_array($column_args)) { $column_args = array('show' => $column_args); } } else { $column_args = array(); } $column_args = wp_parse_args($column_args, array('show' => false)); $this->register($ctype->name, $column_args); return $args; }
private static function create_side(&$args, $direction) { $object = _p2p_pluck($args, $direction); if (in_array($object, array('user', 'attachment'))) { $object_type = $object; } else { $object_type = 'post'; } $query_vars = _p2p_pluck($args, $direction . '_query_vars'); if ('post' == $object_type) { $query_vars['post_type'] = (array) $object; } $class = 'P2P_Side_' . ucfirst($object_type); return new $class($query_vars); }
public function __construct($args, $sides) { $this->side = $sides; $this->set_self_connections($args); $this->set_cardinality(_p2p_pluck($args, 'cardinality')); $labels = array(); foreach (array('from', 'to') as $key) { $labels[$key] = (array) _p2p_pluck($args, $key . '_labels'); } $this->labels = $labels; $this->fields = $this->expand_fields(_p2p_pluck($args, 'fields')); foreach ($args as $key => $value) { $this->{$key} = $value; } }
public static function register($args) { if (isset($args['name'])) { if (strlen($args['name']) > 44) { trigger_error(sprintf("Connection name '%s' is longer than 44 characters.", $args['name']), E_USER_WARNING); return false; } } else { trigger_error("Connection types without a 'name' parameter are deprecated.", E_USER_WARNING); } $args = wp_parse_args($args, array('name' => false, 'from_object' => 'post', 'to_object' => 'post', 'from' => 'post', 'to' => 'post', 'from_query_vars' => array(), 'to_query_vars' => array(), 'data' => array(), 'cardinality' => 'many-to-many', 'prevent_duplicates' => true, 'self_connections' => false, 'sortable' => false, 'title' => array(), 'from_labels' => '', 'to_labels' => '', 'reciprocal' => false)); $sides = array(); foreach (array('from', 'to') as $direction) { $object = _p2p_pluck($args, $direction); if ('user' == $object) { $args[$direction . '_object'] = 'user'; } elseif ('attachment' == $object) { $args[$direction . '_object'] = 'attachment'; } if ('post' == $args[$direction . '_object']) { $validated = array(); foreach ((array) $object as $ptype) { if (!post_type_exists($ptype)) { trigger_error("Post type '{$ptype}' is not defined."); } else { $validated[] = $ptype; } } if (empty($validated)) { $validated = array('post'); } $args[$direction . '_query_vars']['post_type'] = $validated; } } if (!$args['name']) { $args['name'] = md5(serialize(array_values(wp_array_slice_assoc($args, array('from_object', 'to_object', 'from_query_vars', 'to_query_vars', 'data'))))); } $args = apply_filters('p2p_connection_type_args', $args); $ctype = new P2P_Connection_Type($args); if (isset(self::$instances[$ctype->name])) { trigger_error("Connection type '{$ctype->name}' is already defined.", E_USER_NOTICE); } self::$instances[$ctype->name] = $ctype; return $ctype; }
function filter_ctypes($ctype, $args) { if (isset($args['admin_box'])) { $box_args = _p2p_pluck($args, 'admin_box'); if (!is_array($box_args)) { $box_args = array('show' => $box_args); } } else { $box_args = array(); } foreach (array('can_create_post') as $key) { if (isset($args[$key])) { $box_args[$key] = _p2p_pluck($args, $key); } } $box_args = wp_parse_args($box_args, array('show' => 'any', 'context' => 'side', 'priority' => 'default', 'can_create_post' => true)); $this->register($ctype->name, $box_args); return $args; }
function translate_qv($qv) { if (isset($qv['p2p:include'])) { $qv['include'] = _p2p_pluck($qv, 'p2p:include'); } if (isset($qv['p2p:exclude'])) { $qv['exclude'] = _p2p_pluck($qv, 'p2p:exclude'); } if (isset($qv['p2p:search']) && $qv['p2p:search']) { $qv['search'] = '*' . _p2p_pluck($qv, 'p2p:search') . '*'; } if (isset($qv['p2p:page']) && $qv['p2p:page'] > 0) { if (isset($qv['p2p:per_page']) && $qv['p2p:per_page'] > 0) { $qv['number'] = $qv['p2p:per_page']; $qv['offset'] = $qv['p2p:per_page'] * ($qv['p2p:page'] - 1); } } return $qv; }
public static function register($args) { $args = wp_parse_args($args, array('name' => false, 'from_object' => 'post', 'to_object' => 'post', 'from' => 'post', 'to' => 'post', 'from_query_vars' => array(), 'to_query_vars' => array(), 'data' => array(), 'cardinality' => 'many-to-many', 'prevent_duplicates' => true, 'sortable' => false, 'title' => array(), 'from_labels' => '', 'to_labels' => '', 'reciprocal' => false)); $sides = array(); foreach (array('from', 'to') as $direction) { $object = _p2p_pluck($args, $direction); if ('user' == $object) { $args[$direction . '_object'] = 'user'; } elseif ('attachment' == $object) { $args[$direction . '_object'] = 'attachment'; } if ('post' == $args[$direction . '_object']) { $validated = array(); foreach ((array) $object as $ptype) { if (!post_type_exists($ptype)) { trigger_error("Post type '{$ptype}' is not defined."); } else { $validated[] = $ptype; } } if (empty($validated)) { $validated = array('post'); } $args[$direction . '_query_vars']['post_type'] = $validated; } } if (!$args['name']) { $args['name'] = md5(serialize(array_values(wp_array_slice_assoc($args, array('from_object', 'to_object', 'from_query_vars', 'to_query_vars', 'data'))))); } if ($args['from_object'] == $args['to_object'] && 'post' == $args['from_object']) { $class = 'P2P_Connection_Type'; } else { $class = 'Generic_Connection_Type'; } $ctype = new $class($args); if (isset(self::$instances[$ctype->name])) { trigger_error('Connection type is already defined.', E_USER_NOTICE); } self::$instances[$ctype->name] = $ctype; return $ctype; }
/** * Sets 'p2p_type' => array( connection_type => direction ) * * @return: * null means ignore current query * false means trigger 404 * true means proceed */ static function expand_connected_type(&$q, $item, $object_type) { if (!isset($q['connected_type'])) { return; } $ctypes = (array) _p2p_pluck($q, 'connected_type'); if (isset($q['connected_direction'])) { $directions = (array) _p2p_pluck($q, 'connected_direction'); } else { $directions = array(); } $p2p_types = array(); foreach ($ctypes as $i => $p2p_type) { $ctype = p2p_type($p2p_type); if (!$ctype) { continue; } if (isset($directions[$i])) { $directed = $ctype->set_direction($directions[$i]); } else { $directed = self::find_direction($ctype, $item, $object_type); } if (!$directed) { continue; } $p2p_types[$p2p_type] = $directed->get_direction(); } if (empty($p2p_types)) { return false; } if (1 == count($p2p_types)) { $q = $directed->get_connected_args($q); } else { $q['p2p_type'] = $p2p_types; } return true; }
/** @internal */ function _p2p_back_compat_args($argv) { if (count($argv) > 1) { $args = array(); foreach (array('from', 'to', 'reciprocal') as $i => $key) { if (isset($argv[$i])) { $args[$key] = $argv[$i]; } } } else { $args = $argv[0]; } if (isset($args['id'])) { $args['name'] = _p2p_pluck($args, 'id'); } if (isset($args['show_ui'])) { $args['admin_box'] = array('show' => _p2p_pluck($args, 'show_ui')); if (isset($args['context'])) { $args['admin_box']['context'] = _p2p_pluck($args, 'context'); } } return $args; }