NEXT craftinamerica.org. Base setup for headless wordpress https://www.craftinamerica.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

api.php 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. <?php
  2. /**
  3. * Register a connection type.
  4. *
  5. * @link https://github.com/scribu/wp-posts-to-posts/wiki/p2p_register_connection_type
  6. *
  7. * @param array $args
  8. * @return bool|object False on failure, P2P_Connection_Type instance on success.
  9. */
  10. function p2p_register_connection_type( $args ) {
  11. if ( !did_action('init') ) {
  12. trigger_error( "Connection types should not be registered before the 'init' hook." );
  13. }
  14. $argv = func_get_args();
  15. if ( count( $argv ) > 1 ) {
  16. $args = array();
  17. foreach ( array( 'from', 'to', 'reciprocal' ) as $i => $key ) {
  18. if ( isset( $argv[ $i ] ) )
  19. $args[ $key ] = $argv[ $i ];
  20. }
  21. } else {
  22. $args = $argv[0];
  23. }
  24. if ( isset( $args['id'] ) ) {
  25. $args['name'] = _p2p_pluck( $args, 'id' );
  26. }
  27. if ( isset( $args['prevent_duplicates'] ) ) {
  28. $args['duplicate_connections'] = !$args['prevent_duplicates'];
  29. }
  30. if ( isset( $args['show_ui'] ) ) {
  31. $args['admin_box'] = array(
  32. 'show' => _p2p_pluck( $args, 'show_ui' )
  33. );
  34. if ( isset( $args['context'] ) )
  35. $args['admin_box']['context'] = _p2p_pluck( $args, 'context' );
  36. }
  37. if ( !isset( $args['admin_box'] ) )
  38. $args['admin_box'] = 'any';
  39. $ctype = P2P_Connection_Type_Factory::register( $args );
  40. do_action( 'p2p_registered_connection_type', $ctype, $args );
  41. return $ctype;
  42. }
  43. /**
  44. * Get a connection type.
  45. *
  46. * @param string $p2p_type
  47. *
  48. * @return bool|object False if connection type not found, P2P_Connection_Type instance on success.
  49. */
  50. function p2p_type( $p2p_type ) {
  51. return P2P_Connection_Type_Factory::get_instance( $p2p_type );
  52. }
  53. /**
  54. * Check if a certain connection exists.
  55. *
  56. * @param string $p2p_type A valid connection type.
  57. * @param array $args Query args.
  58. *
  59. * @return bool
  60. */
  61. function p2p_connection_exists( $p2p_type, $args = array() ) {
  62. $args['fields'] = 'count';
  63. $r = p2p_get_connections( $p2p_type, $args );
  64. return (bool) $r;
  65. }
  66. /**
  67. * Retrieve connections.
  68. *
  69. * @param string $p2p_type A valid connection type.
  70. * @param array $args Query args:
  71. *
  72. * - 'direction': Can be 'from', 'to' or 'any'
  73. * - 'from': Object id. The first end of the connection. (optional)
  74. * - 'to': Object id. The second end of the connection. (optional)
  75. * - 'fields': Which field of the connection to return. Can be:
  76. * 'all', 'object_id', 'p2p_from', 'p2p_to', 'p2p_id' or 'count'
  77. *
  78. * @return array
  79. */
  80. function p2p_get_connections( $p2p_type, $args = array() ) {
  81. $args = wp_parse_args( $args, array(
  82. 'direction' => 'from',
  83. 'from' => 'any',
  84. 'to' => 'any',
  85. 'fields' => 'all',
  86. ) );
  87. $r = array();
  88. foreach ( _p2p_expand_direction( $args['direction'] ) as $direction ) {
  89. $dirs = array( $args['from'], $args['to'] );
  90. if ( 'to' == $direction ) {
  91. $dirs = array_reverse( $dirs );
  92. }
  93. if ( 'object_id' == $args['fields'] )
  94. $fields = ( 'to' == $direction ) ? 'p2p_from' : 'p2p_to';
  95. else
  96. $fields = $args['fields'];
  97. $r = array_merge( $r, _p2p_get_connections( $p2p_type, array(
  98. 'from' => $dirs[0],
  99. 'to' => $dirs[1],
  100. 'fields' => $fields
  101. ) ) );
  102. }
  103. if ( 'count' == $args['fields'] )
  104. return array_sum( $r );
  105. return $r;
  106. }
  107. /** @internal */
  108. function _p2p_get_connections( $p2p_type, $args = array() ) {
  109. global $wpdb;
  110. $where = $wpdb->prepare( 'WHERE p2p_type = %s', $p2p_type );
  111. foreach ( array( 'from', 'to' ) as $key ) {
  112. if ( 'any' == $args[ $key ] )
  113. continue;
  114. if ( empty( $args[ $key ] ) )
  115. return array();
  116. $value = scbUtil::array_to_sql( _p2p_normalize( $args[ $key ] ) );
  117. $where .= " AND p2p_$key IN ($value)";
  118. }
  119. switch ( $args['fields'] ) {
  120. case 'p2p_id':
  121. case 'p2p_from':
  122. case 'p2p_to':
  123. $sql_field = $args['fields'];
  124. break;
  125. case 'count':
  126. $sql_field = 'COUNT(*)';
  127. break;
  128. default:
  129. $sql_field = '*';
  130. }
  131. $query = "SELECT $sql_field FROM $wpdb->p2p $where";
  132. if ( '*' == $sql_field )
  133. return $wpdb->get_results( $query );
  134. else
  135. return $wpdb->get_col( $query );
  136. }
  137. /**
  138. * Retrieve a single connection.
  139. *
  140. * @param int $p2p_id The connection id.
  141. *
  142. * @return object
  143. */
  144. function p2p_get_connection( $p2p_id ) {
  145. global $wpdb;
  146. return $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->p2p WHERE p2p_id = %d", $p2p_id ) );
  147. }
  148. /**
  149. * Create a connection.
  150. *
  151. * @param int $p2p_type A valid connection type.
  152. * @param array $args Connection information.
  153. *
  154. * @return bool|int False on failure, p2p_id on success.
  155. */
  156. function p2p_create_connection( $p2p_type, $args ) {
  157. global $wpdb;
  158. $args = wp_parse_args( $args, array(
  159. 'direction' => 'from',
  160. 'from' => false,
  161. 'to' => false,
  162. 'meta' => array()
  163. ) );
  164. list( $from ) = _p2p_normalize( $args['from'] );
  165. list( $to ) = _p2p_normalize( $args['to'] );
  166. if ( !$from || !$to )
  167. return false;
  168. $dirs = array( $from, $to );
  169. if ( 'to' == $args['direction'] ) {
  170. $dirs = array_reverse( $dirs );
  171. }
  172. $wpdb->insert( $wpdb->p2p, array(
  173. 'p2p_type' => $p2p_type,
  174. 'p2p_from' => $dirs[0],
  175. 'p2p_to' => $dirs[1]
  176. ) );
  177. $p2p_id = $wpdb->insert_id;
  178. foreach ( $args['meta'] as $key => $value )
  179. p2p_add_meta( $p2p_id, $key, $value );
  180. do_action( 'p2p_created_connection', $p2p_id );
  181. return $p2p_id;
  182. }
  183. /**
  184. * Delete one or more connections.
  185. *
  186. * @param int $p2p_type A valid connection type.
  187. * @param array $args Connection information.
  188. *
  189. * @return int Number of connections deleted
  190. */
  191. function p2p_delete_connections( $p2p_type, $args = array() ) {
  192. $args['fields'] = 'p2p_id';
  193. return p2p_delete_connection( p2p_get_connections( $p2p_type, $args ) );
  194. }
  195. /**
  196. * Delete connections using p2p_ids.
  197. *
  198. * @param int|array $p2p_id Connection ids
  199. *
  200. * @return int Number of connections deleted
  201. */
  202. function p2p_delete_connection( $p2p_id ) {
  203. global $wpdb;
  204. if ( empty( $p2p_id ) )
  205. return 0;
  206. $p2p_ids = array_map( 'absint', (array) $p2p_id );
  207. do_action( 'p2p_delete_connections', $p2p_ids );
  208. $where = "WHERE p2p_id IN (" . implode( ',', $p2p_ids ) . ")";
  209. $count = $wpdb->query( "DELETE FROM $wpdb->p2p $where" );
  210. $wpdb->query( "DELETE FROM $wpdb->p2pmeta $where" );
  211. return $count;
  212. }
  213. function p2p_get_meta( $p2p_id, $key = '', $single = false ) {
  214. return get_metadata( 'p2p', $p2p_id, $key, $single );
  215. }
  216. function p2p_update_meta( $p2p_id, $key, $value, $prev_value = '' ) {
  217. return update_metadata( 'p2p', $p2p_id, $key, $value, $prev_value );
  218. }
  219. function p2p_add_meta( $p2p_id, $key, $value, $unique = false ) {
  220. return add_metadata( 'p2p', $p2p_id, $key, $value, $unique );
  221. }
  222. function p2p_delete_meta( $p2p_id, $key, $value = '' ) {
  223. return delete_metadata( 'p2p', $p2p_id, $key, $value );
  224. }
  225. /**
  226. * List some items.
  227. *
  228. * @param object|array A P2P_List instance, a WP_Query instance, or a list of post objects
  229. * @param array $args (optional)
  230. */
  231. function p2p_list_posts( $posts, $args = array() ) {
  232. if ( is_a( $posts, 'P2P_List' ) ) {
  233. $list = $posts;
  234. } else {
  235. if ( is_a( $posts, 'WP_Query' ) )
  236. $posts = $posts->posts;
  237. $list = new P2P_List( $posts, 'P2P_Item_Post' );
  238. }
  239. return P2P_List_Renderer::render( $list, $args );
  240. }
  241. /**
  242. * Given a list of objects and another list of connected items,
  243. * distribute each connected item to it's respective counterpart.
  244. *
  245. * @param array List of objects
  246. * @param array List of connected objects
  247. * @param string Name of connected array property
  248. */
  249. function p2p_distribute_connected( $items, $connected, $prop_name ) {
  250. $indexed_list = array();
  251. foreach ( $items as $item ) {
  252. $item->$prop_name = array();
  253. $indexed_list[ $item->ID ] = $item;
  254. }
  255. $groups = scb_list_group_by( $connected, '_p2p_get_other_id' );
  256. foreach ( $groups as $outer_item_id => $connected_items ) {
  257. $indexed_list[ $outer_item_id ]->$prop_name = $connected_items;
  258. }
  259. }