Overview

Classes

  • Papi_Admin
  • Papi_Admin_Ajax
  • Papi_Admin_Assets
  • Papi_Admin_Management_Pages
  • Papi_Admin_Menu
  • Papi_Admin_Meta_Box
  • Papi_Admin_Meta_Box_Tabs
  • Papi_Admin_Option_Handler
  • Papi_Admin_Post_Handler
  • Papi_Admin_View
  • Papi_Attachment_Type
  • Papi_Conditional_Rules
  • Papi_Container
  • Papi_Core_Autoload
  • Papi_Core_Conditional
  • Papi_Core_Conditional_Rule
  • Papi_Core_Data_Handler
  • Papi_Core_Page
  • Papi_Core_Property
  • Papi_Core_Type
  • Papi_Loader
  • Papi_Option_Page
  • Papi_Option_Type
  • Papi_Page_Type
  • Papi_Page_Type_Meta
  • Papi_Porter
  • Papi_Porter_Driver
  • Papi_Porter_Driver_Core
  • Papi_Post_Page
  • Papi_Property
  • Papi_Property_Bool
  • Papi_Property_Checkbox
  • Papi_Property_Color
  • Papi_Property_Datetime
  • Papi_Property_Divider
  • Papi_Property_Dropdown
  • Papi_Property_Editor
  • Papi_Property_Email
  • Papi_Property_File
  • Papi_Property_Flexible
  • Papi_Property_Gallery
  • Papi_Property_Hidden
  • Papi_Property_Html
  • Papi_Property_Image
  • Papi_Property_Link
  • Papi_Property_Number
  • Papi_Property_Post
  • Papi_Property_Radio
  • Papi_Property_Reference
  • Papi_Property_Relationship
  • Papi_Property_Repeater
  • Papi_Property_String
  • Papi_Property_Term
  • Papi_Property_Text
  • Papi_Property_Url
  • Papi_Property_User

Functions

  • current_page
  • papi
  • papi_action_delete_value
  • papi_action_include
  • papi_append_post_type_query
  • papi_body_class
  • papi_cache_delete
  • papi_cache_get
  • papi_cache_key
  • papi_cache_set
  • papi_camel_case
  • papi_cast_string_value
  • papi_convert_to_string
  • papi_current_user_is_allowed
  • papi_dashify
  • papi_delete_field
  • papi_delete_option
  • papi_delete_property_meta_value
  • papi_display_page_type
  • papi_doing_ajax
  • papi_esc_html
  • papi_f
  • papi_field
  • papi_field_shortcode
  • papi_field_value
  • papi_fields
  • papi_filter_conditional_rule_allowed
  • papi_filter_core_load_one_type_on
  • papi_filter_format_value
  • papi_filter_load_value
  • papi_filter_settings_directories
  • papi_filter_settings_only_page_type
  • papi_filter_settings_page_type_column_title
  • papi_filter_settings_show_page_type
  • papi_filter_settings_show_standard_page_type
  • papi_filter_settings_show_standard_page_type_in_filter
  • papi_filter_settings_sort_order
  • papi_filter_settings_standard_page_description
  • papi_filter_settings_standard_page_name
  • papi_filter_settings_standard_page_thumbnail
  • papi_filter_update_value
  • papi_from_property_array_slugs
  • papi_get_all_files_in_directory
  • papi_get_all_page_type_files
  • papi_get_all_page_types
  • papi_get_box_property
  • papi_get_class_name
  • papi_get_field
  • papi_get_file_path
  • papi_get_number_of_pages
  • papi_get_only_objects
  • papi_get_option
  • papi_get_options_and_properties
  • papi_get_or_post
  • papi_get_page
  • papi_get_page_new_url
  • papi_get_page_query_strings
  • papi_get_page_type
  • papi_get_page_type_base_path
  • papi_get_page_type_by_id
  • papi_get_page_type_by_post_id
  • papi_get_page_type_id
  • papi_get_page_type_key
  • papi_get_page_type_meta_value
  • papi_get_page_type_name
  • papi_get_page_type_template
  • papi_get_parent_post_id
  • papi_get_post_id
  • papi_get_post_type
  • papi_get_post_type_label
  • papi_get_post_types
  • papi_get_property_class_name
  • papi_get_property_meta_value
  • papi_get_property_options
  • papi_get_property_type
  • papi_get_property_type_key
  • papi_get_property_type_key_f
  • papi_get_qs
  • papi_get_sanitized_post
  • papi_get_slugs
  • papi_get_tab_options
  • papi_html_name
  • papi_html_tag
  • papi_include_template
  • papi_is_empty
  • papi_is_json
  • papi_is_method
  • papi_is_option_page
  • papi_is_option_type
  • papi_is_page_type
  • papi_is_property
  • papi_is_property_type_key
  • papi_is_rule
  • papi_management_page_type_render_box
  • papi_maybe_convert_to_array
  • papi_maybe_convert_to_object
  • papi_maybe_get_callable_value
  • papi_maybe_json_decode
  • papi_maybe_json_encode
  • papi_nl2br
  • papi_option_shortcode
  • papi_option_type_exists
  • papi_page_type_exists
  • papi_populate_properties
  • papi_property
  • papi_remove_papi
  • papi_remove_trailing_quotes
  • papi_render_html_tag
  • papi_render_properties
  • papi_render_property
  • papi_require_text
  • papi_required_html
  • papi_rule
  • papi_santize_data
  • papi_set_page_type_id
  • papi_setup_tabs
  • papi_slugify
  • papi_sort_order
  • papi_tab
  • papi_template
  • papi_template_include
  • papi_to_array
  • papi_to_property_array_slugs
  • papi_translate_keys
  • papi_underscorify
  • papi_update_field
  • papi_update_option
  • papi_update_property_meta_value
  • papi_with
  • papify
  • the_papi_field
  • the_papi_option
  • the_papi_page_type_name
  • Overview
  • Class
  1: <?php
  2: 
  3: /**
  4:  * Relationship property that can handle
  5:  * more than one relationship between posts.
  6:  */
  7: class Papi_Property_Relationship extends Papi_Property {
  8: 
  9:     /**
 10:      * The convert type.
 11:      *
 12:      * @var string
 13:      */
 14:     public $convert_type = 'array';
 15: 
 16:     /**
 17:      * The default value.
 18:      *
 19:      * @var array
 20:      */
 21:     public $default_value = [];
 22: 
 23:     /**
 24:      * Convert WordPress post object to a item object.
 25:      *
 26:      * @param  WP_Post $post
 27:      *
 28:      * @return object
 29:      */
 30:     protected function convert_post_to_item( WP_Post $post ) {
 31:         return (object) [
 32:             'id'    => $post->ID,
 33:             'title' => $post->post_title
 34:         ];
 35:     }
 36: 
 37:     /**
 38:      * Format the value of the property before it's returned
 39:      * to WordPress admin or the site.
 40:      *
 41:      * @param  mixed  $values
 42:      * @param  string $slug
 43:      * @param  int    $post_id
 44:      *
 45:      * @return array
 46:      */
 47:     public function format_value( $values, $slug, $post_id ) {
 48:         if ( is_array( $values ) || is_object( $values ) ) {
 49:             $items  = $this->get_settings()->items;
 50:             $result = [];
 51: 
 52:             foreach ( $values as $key => $id ) {
 53:                 // Backwards compatibility with array `id` and `id`.
 54:                 $id  = is_array( $id ) ? $id['id'] : $id;
 55: 
 56:                 if ( empty( $id ) ) {
 57:                     continue;
 58:                 }
 59: 
 60:                 if ( papi_is_empty( $items ) ) {
 61:                     $post = get_post( $id );
 62: 
 63:                     if ( empty( $post ) ) {
 64:                         continue;
 65:                     }
 66: 
 67:                     $result[] = $post;
 68:                 } else {
 69:                     $item = array_filter( $items, function ( $item ) use ( $id ) {
 70:                         return wp_list_pluck( [$item], 'id' )[0] === (int) $id;
 71:                     } );
 72: 
 73:                     $result[] = papi_maybe_convert_to_object( array_values( $item )[0] );
 74:                 }
 75:             }
 76: 
 77:             return $this->sort_value( $result, $slug, $post_id );
 78:         }
 79: 
 80:         return $this->default_value;
 81:     }
 82: 
 83:     /**
 84:      * Get default settings.
 85:      *
 86:      * @return array
 87:      */
 88:     public function get_default_settings() {
 89:         return [
 90:             'items'        => [],
 91:             'limit'        => -1,
 92:             'only_once'    => false,
 93:             'post_type'    => 'page',
 94:             'title'        => __( 'Post', 'papi' ),
 95:             'query'        => [],
 96:             'show_sort_by' => true
 97:         ];
 98:     }
 99: 
100:     /**
101:      * Get sort option value.
102:      *
103:      * @param  int $post_id
104:      *
105:      * @return string
106:      */
107:     public function get_sort_option( $post_id ) {
108:         $slug = $this->html_id( 'sort_option' );
109:         $slug = str_replace( '][', '_', $slug );
110:         $slug = str_replace( '[', '_', $slug );
111:         $slug = str_replace( ']', '', $slug );
112: 
113:         return papi_get_property_meta_value( $post_id, $slug );
114:     }
115: 
116:     /**
117:      * Get sort options for relationship property.
118:      *
119:      * @return array
120:      */
121:     public static function get_sort_options() {
122:         $sort_options = [];
123: 
124:         $sort_options[__( 'Select', 'papi' )] = null;
125: 
126:         $sort_options[__( 'Name (alphabetically)', 'papi' )] = function ( $a, $b ) {
127:             // Backwards compatibility with both `post_title` and `title`.
128:             return strcmp(
129:                 strtolower( isset( $a->post_title ) ? $a->post_title : $a->title ),
130:                 strtolower( isset( $b->post_title ) ? $b->post_title : $b->title )
131:             );
132:         };
133: 
134:         $sort_options[__( 'Post created date (ascending)', 'papi' )] = function ( $a, $b ) {
135:             return strtotime( $a->post_date ) > strtotime( $b->post_date );
136:         };
137: 
138:         $sort_options[__( 'Post created date (descending)', 'papi' )] = function ( $a, $b ) {
139:             return strtotime( $a->post_date ) < strtotime( $b->post_date );
140:         };
141: 
142:         $sort_options[__( 'Post id (ascending)', 'papi' )] = function ( $a, $b ) {
143:             // Backwards compatibility with both `ID` and `id`.
144:             return isset( $a->ID ) ? $a->ID > $b->ID : $a->id > $b->id;
145:         };
146: 
147:         $sort_options[__( 'Post id (descending)', 'papi' )] = function ( $a, $b ) {
148:             // Backwards compatibility with both `ID` and `id`.
149:             return isset( $a->ID ) ? $a->ID < $b->ID : $a->id < $b->id;
150:         };
151: 
152:         $sort_options[__( 'Post order value (ascending)', 'papi' )] = function ( $a, $b ) {
153:             return $a->menu_order > $b->menu_order;
154:         };
155: 
156:         $sort_options[__( 'Post order value (descending)', 'papi' )] = function ( $a, $b ) {
157:             return $a->menu_order < $b->menu_order;
158:         };
159: 
160:         $sort_options[__( 'Post modified date (ascending)', 'papi' )] = function ( $a, $b ) {
161:             return strtotime( $a->post_modified ) >
162:                 strtotime( $b->post_modified );
163:         };
164: 
165:         $sort_options[__( 'Post modified date (descending)', 'papi' )] = function ( $a, $b ) {
166:             return strtotime( $a->post_modified ) <
167:                 strtotime( $b->post_modified );
168:         };
169: 
170:         return apply_filters(
171:             'papi/property/relationship/sort_options',
172:             $sort_options
173:         );
174:     }
175: 
176:     /**
177:      * Get items to display from settings.
178:      *
179:      * @param  object $settings
180:      *
181:      * @return array
182:      */
183:     protected function get_items( $settings ) {
184:         if ( is_array( $settings->items ) && ! empty( $settings->items ) ) {
185:             $mapping = function ( $item ) {
186:                 return is_array( $item ) ?
187:                     isset( $item['id'] ) && isset( $item['title'] ) :
188:                     isset( $item->id ) && isset( $item->title );
189:             };
190: 
191:             return array_map(
192:                 'papi_maybe_convert_to_object',
193:                 array_filter( $settings->items, $mapping )
194:             );
195:         }
196: 
197:         // By default we add posts per page key with the value -1 (all).
198:         if ( ! isset( $settings->query['posts_per_page'] ) ) {
199:             $settings->query['posts_per_page'] = -1;
200:         }
201: 
202:         // Prepare arguments for WP_Query.
203:         $args = array_merge( $settings->query, [
204:             'post_type'              => papi_to_array( $settings->post_type ),
205:             'no_found_rows'          => true,
206:             'update_post_meta_cache' => false,
207:             'update_post_term_cache' => false
208:         ] );
209: 
210:         $query = new WP_Query( $args );
211:         $items = $query->get_posts();
212: 
213:         return array_map(
214:             [$this, 'convert_post_to_item'],
215:             papi_get_only_objects( $items )
216:         );
217:     }
218: 
219:     /**
220:      * Render property html.
221:      */
222:     public function html() {
223:         $post_id       = papi_get_post_id();
224:         $slug          = $this->html_name();
225:         $settings      = $this->get_settings();
226:         $settings_json = [];
227:         $sort_option   = $this->get_sort_option( $post_id );
228:         $sort_options  = static::get_sort_options();
229:         $values        = papi_get_only_objects( $this->get_value() );
230:         $items         = $this->get_items( $settings );
231: 
232:         if ( papi_is_empty( $settings->items ) ) {
233:             $values = array_map( [$this, 'convert_post_to_item'], $values );
234:         } else {
235:             foreach ( $sort_options as $key => $sort ) {
236:                 if ( strpos( $key, 'Post' ) === 0 ) {
237:                     unset( $sort_options[$key] );
238:                 }
239:             }
240:         }
241: 
242:         // Convert all sneak case key to camel case.
243:         foreach ( (array) $settings as $key => $val ) {
244:             if ( ! is_string( $key ) || ! in_array( $key, ['only_once', 'limit'] ) ) {
245:                 continue;
246:             }
247: 
248:             $settings_json[papi_camel_case( $key )] = $val;
249:         }
250:         ?>
251:         <div class="papi-property-relationship" data-settings='<?php echo json_encode( $settings_json ); ?>'>
252:             <input type="hidden" name="<?php echo $slug; ?>[]" data-papi-rule="<?php echo $slug; ?>" />
253:             <div class="relationship-inner">
254:                 <div class="relationship-top-left">
255:                     <label for="<?php echo $this->html_id( 'search' ); ?>"><?php _e( 'Search', 'papi' ); ?></label>
256:                     <input id="<?php echo $this->html_id( 'search' ); ?>" type="search" />
257:                 </div>
258:                 <div class="relationship-top-right">
259:                     <?php if ( $settings->show_sort_by ): ?>
260:                         <label for="<?php echo $this->html_id( 'sort_option' ); ?>"><?php _e( 'Sort by', 'papi' ); ?></label>
261:                         <select id="<?php echo $this->html_id( 'sort_option' ); ?>" name="<?php echo $this->html_id( 'sort_option' ); ?>">
262:                             <?php foreach ( $sort_options as $key => $v ): ?>
263:                                 <option value="<?php echo $key; ?>" <?php echo $key === $sort_option ? 'selected="selected"' : ''; ?>><?php echo $key; ?></option>
264:                             <?php endforeach; ?>
265:                         </select>
266:                     <?php endif; ?>
267:                 </div>
268:                 <div class="papi-clear"></div>
269:             </div>
270:             <div class="relationship-inner">
271:                 <div class="relationship-left">
272:                     <ul>
273:                         <?php
274:                         foreach ( $items as $item ):
275:                             if ( ! empty( $item->title ) ):
276:                                 ?>
277:                                 <li>
278:                                     <input type="hidden"
279:                                            data-name="<?php echo $slug; ?>[]"
280:                                            value="<?php echo $item->id; ?>"/>
281:                                     <a href="#"><?php echo $item->title; ?></a>
282:                                     <span class="icon plus"></span>
283:                                 </li>
284:                             <?php
285:                             endif;
286:                         endforeach;
287:                         ?>
288:                     </ul>
289:                 </div>
290:                 <div class="relationship-right">
291:                     <ul>
292:                         <?php foreach ( $values as $item ): ?>
293:                             <li>
294:                                 <input type="hidden" name="<?php echo $slug; ?>[]"
295:                                        value="<?php echo $item->id; ?>"/>
296:                                 <a href="#"><?php echo $item->title; ?></a>
297:                                 <span class="icon minus"></span>
298:                             </li>
299:                         <?php endforeach; ?>
300:                     </ul>
301:                 </div>
302:                 <div class="papi-clear"></div>
303:             </div>
304:         </div>
305:     <?php
306:     }
307: 
308:     /**
309:      * Import value to the property.
310:      *
311:      * @param  mixed  $value
312:      * @param  string $slug
313:      * @param  int    $post_id
314:      *
315:      * @return mixed
316:      */
317:     public function import_value( $value, $slug, $post_id ) {
318:         if ( ! is_array( $value ) && ! is_object( $value ) && ! is_numeric( $value ) ) {
319:             return;
320:         }
321: 
322:         $values = [];
323: 
324:         foreach ( papi_to_array( $value ) as $index => $val ) {
325:             if ( $val instanceof WP_Post ) {
326:                 $values[] = $val->ID;
327:             }
328: 
329:             if ( is_object( $val ) && isset( $val->id ) ) {
330:                 $values[] = (int) $val->id;
331:             }
332: 
333:             if ( is_numeric( $val ) ) {
334:                 $values[] = (int) $val;
335:             }
336:         }
337: 
338:         return $values;
339:     }
340: 
341:     /**
342:      * Change value after it's loaded from the database.
343:      *
344:      * @param  mixed  $values
345:      * @param  string $slug
346:      * @param  int    $post_id
347:      *
348:      * @return mixed
349:      */
350:     public function load_value( $values, $slug, $post_id ) {
351:         return (array) papi_maybe_json_decode( maybe_unserialize( $values ), true );
352:     }
353: 
354:     /**
355:      * Sort the values.
356:      *
357:      * @param  array  $values
358:      * @param  string $slug
359:      * @param  int    $post_id
360:      *
361:      * @return array
362:      */
363:     public function sort_value( $values, $slug, $post_id ) {
364:         $sort_option  = $this->get_sort_option( $post_id );
365:         $sort_options = static::get_sort_options();
366: 
367:         if ( empty( $sort_option ) || ! isset( $sort_options[$sort_option] ) || is_null( $sort_options[$sort_option] ) ) {
368:             return $values;
369:         }
370: 
371:         usort( $values, $sort_options[$sort_option] );
372: 
373:         return $values;
374:     }
375: 
376:     /**
377:      * Sort the values on update.
378:      *
379:      * @param  mixed  $values
380:      * @param  string $slug
381:      * @param  int    $post_id
382:      *
383:      * @return string
384:      */
385:     public function update_value( $values, $slug, $post_id ) {
386:         $values = $this->format_value( $values, $slug, $post_id );
387:         $values = array_map( function ( $item ) {
388:             if ( $item instanceof WP_Post ) {
389:                 $item = $this->convert_post_to_item( $item );
390:             }
391: 
392:             if ( isset( $item->title ) ) {
393:                 unset( $item->title );
394:             }
395: 
396:             return $item;
397:         }, $values );
398: 
399:         return json_encode( $values );
400:     }
401: }
402: 
API documentation generated by ApiGen