Fieldmanager
  • Package
  • Class
  • Tree
  • Todo

Packages

  • Fieldmanager
    • Context
    • Datasource
    • Field
    • Util
  • None

Classes

  • Fieldmanager_Autocomplete
  • Fieldmanager_Checkbox
  • Fieldmanager_Checkboxes
  • Fieldmanager_Colorpicker
  • Fieldmanager_Datepicker
  • Fieldmanager_DraggablePost
  • Fieldmanager_Field
  • Fieldmanager_Grid
  • Fieldmanager_Group
  • Fieldmanager_Hidden
  • Fieldmanager_Link
  • Fieldmanager_Media
  • Fieldmanager_Options
  • Fieldmanager_Password
  • Fieldmanager_Radios
  • Fieldmanager_RichTextArea
  • Fieldmanager_Select
  • Fieldmanager_TextArea
  • Fieldmanager_TextField
  1 <?php
  2 /**
  3  * An interface for dragging posts from a repository to assorted buckets.
  4  *
  5  * This field might be deprecated in a future version of Fieldmanager. It is
  6  * preferable to use {@link https://github.com/alleyinteractive/fm-zones}
  7  * instead.
  8  *
  9  * @package Fieldmanager_Field
 10  */
 11 class Fieldmanager_DraggablePost extends Fieldmanager_Field {
 12 
 13     /**
 14      * @var array
 15      * Keyed array defining repository boxes and what their content should be. Keys are the machine names of the repositories. Each can include:
 16      *      - 'label' (string) the publicly displayed label of the box (eg 'News Artickes')
 17      *      - 'post_type' (string or array of strings) post type(s) to select for this box
 18      *      - 'length' (int) number of items to show in the box
 19      *      - 'orderby' (string) field to order the query by, as allowed by WP_Query
 20      *      - 'order' (string) ASC or DESC
 21      *      - 'taxonomy_args' (array) arguments to pass to WP_Query to filter by category (see https://codex.wordpress.
 22      *          org/Class_Reference/WP_Query#Taxonomy_Parameters). If omitted, no taxonomy filtering will be performed.
 23      *      - 'callback' (callable) a custom function to call in lieu of WP_Query to retrieve posts for this repository. The function
 24      *          must have the signature callback($key, $data) and must return an array of post ids. If callback is set, all the above
 25      *          options (except label) will be overridden.
 26      */
 27     public $repositories = array();
 28 
 29     /**
 30      * @var array
 31      * Keyed array defining the bins (destination droppable locations) for the draggable items. Keys are machine names, values are labels.
 32      */
 33     public $bins = array();
 34 
 35     /**
 36      * @var boolean
 37      * Provide "Use image?" checkbox for draggable divs?
 38      */
 39     public $use_image_checkbox = False;
 40 
 41 
 42     /**
 43      * Add scripts and styles and other setup tasks.
 44      * @param string $label
 45      * @param array $options
 46      */
 47     public function __construct( $label = '', $options = array() ) {
 48         parent::__construct( $label, $options );
 49         // Refuse to allow more than one instance of this field type.
 50         $this->limit = 1;
 51 
 52         wp_enqueue_script( 'jquery-ui-draggable' );
 53         wp_enqueue_script( 'jquery-ui-droppable' );
 54         wp_enqueue_script( 'jquery-ui-sortable' );
 55         fm_add_script( 'fm_draggablepost_js', 'js/fieldmanager-draggablepost.js' );
 56         fm_add_style( 'fm_draggablepost_css', 'css/fieldmanager-draggablepost.css' );
 57     }
 58 
 59 
 60     /**
 61      * Massage form data into proper storage format..
 62      * @param array $value
 63      * @return array $value
 64      */
 65     public function presave( $value, $current_values = array() ) {
 66 
 67         foreach ( $this->bins as $bin => $name ) {
 68             if ( isset( $value[$bin] ) ) {
 69                 $value[$bin] = explode(',', $value[$bin]);
 70             }
 71         }
 72 
 73         $image_flags = array();
 74         if ( isset( $value['_image_flags'] ) ) {
 75             foreach ( $value['_image_flags'] as $id => $val ) {
 76                 $image_flags[] = $id;
 77             }
 78             $value['_image_flags'] = $image_flags;
 79         }
 80 
 81         return $value;
 82     }
 83 
 84     /**
 85      * Render form element
 86      * @param mixed $value
 87      * @return string HTML
 88      */
 89     public function form_element( $value ) {
 90         // Avoid null array errors later.
 91         $value['_image_flags'] = isset( $value['_image_flags'] ) ? $value['_image_flags'] : array();
 92 
 93         $all = $this->flatten_arrays( $value );
 94         $out = '<div id="fm-draggablepost"><div class="post-repository-wrapper">';
 95         foreach ( $this->repositories as $name => $repo ) {
 96             $out .= sprintf( '<h2>%s</h2><ul class="post-repository sortables">', $repo['label'] );
 97             if ( isset( $repo['callback'] ) ) {
 98                 $ids = call_user_func( $repo['callback'], $name, $repo );
 99                 if ( !empty( $ids ) ) {
100                     // Return value here should be all numeric post ids, but we'll tolerate non-numerics if they show up.
101                     foreach ( $ids as $id ) {
102                         if ( !is_numeric( $id ) || in_array( $id, $all ) ) {
103                             continue;
104                         }
105                         $out .= $this->draggable_item_html( $id );
106                     }
107                 }
108             }
109             else {
110                 $query_args = array(
111                     'post_type' => $repo['post_type'],
112                     'post_status' => 'publish',
113                     'posts_per_page' => $repo['length'],
114                     'orderby' => $repo['orderby'],
115                     'order' => $repo['order'],
116                     'tax_query' => array($repo['taxonomy_args']),
117                 );
118                 $q = new WP_Query( $query_args );
119                 while ( $q->have_posts() ) {
120                     $q->the_post();
121                     if ( in_array( get_the_ID(), $all ) ) {
122                         continue;
123                     }
124                     $out .= $this->draggable_item_html( get_the_ID() );
125                 }
126             }
127             $out .= "</ul>";
128         }
129         $out .= "</div>";
130         $out .= '<div class="post-bin-wrapper">';
131         foreach ( $this->bins as $name => $bin ) {
132             $out .= sprintf( '<h2>%s</h2>', $bin );
133             $out .= sprintf( '<ul class="post-bin sortables" id="%s-bin"><em class="empty-message">%s</em>', esc_attr( $name ), esc_attr__( 'drop posts here', 'fieldmanager' ) );
134             if ( isset( $value[$name] ) ) {
135                 foreach ( $value[$name] as $id ) {
136                     if ( !$id ) {
137                         continue;
138                     }
139                     $out .= $this->draggable_item_html( $id, in_array( $id, $value['_image_flags'] ) );
140                 }
141             }
142             $out .= "</ul>";
143         }
144 
145         foreach ( $this->bins as $bin => $label ) {
146             $out .= sprintf( '<input type="hidden" value="%s" name="%s" id="%s" />',
147                         empty( $value[$bin] ) ?  '' : implode( ',', $value[$bin] ),
148                         $this->get_form_name() . '[' . $bin . ']',
149                         $bin
150                     );
151         }
152         $out .= '</div></div>';
153         return $out;
154     }
155 
156     /**
157      * Generate the html for a single draggable item
158      * @param int $post_id
159      * @param boolean $use_image_checked if true, render this item with the "use image" checkbox checked (if enabled)
160      * @return string containing the li element.
161      */
162     protected function draggable_item_html( $post_id, $use_image_checked = false ) {
163         $post = get_post( $post_id );
164         $bylines = array();
165         if ( is_plugin_active( 'co-authors-plus/co-authors-plus.php' ) ) {
166             $authors = get_coauthors( $post_id );
167             foreach ($authors as $author) {
168                 $bylines[] = $author->display_name;
169             }
170             if ( empty( $bylines ) ) {
171                 $authorstr = esc_html__( '(no authors)', 'fieldmanager' );
172             }
173             else {
174                 $authorstr = implode(', ', $bylines);
175             }
176         }
177         else {
178             $author = get_userdata( $post->post_author );
179             $authorstr = $author->display_name;
180         }
181 
182         $image_meta = get_post_meta( $post_id, '_thumbnail_id' );
183 
184         $permalink = get_permalink( $post_id );
185 
186         if ( isset( $image_meta[0] ) ) {
187             $image = wp_get_attachment_image( $image_meta[0], array(32,32) );
188         }
189         else{
190             $image = '';
191         }
192 
193         $li = sprintf( '<li class="draggable-post" id="draggable-post-%d" post_id="%d">', $post_id, $post_id );
194         $li_inner = sprintf('<strong><a href="%s" target="_new">%s</a></strong><br />
195                             <small>%s &mdash; %s</small><br />
196                             <small><em>%s %s</em></small>',
197             $permalink,
198             $post->post_title,
199             $post->post_date,
200             $authorstr,
201             $image,
202             $post->post_excerpt
203         );
204 
205         if ( $this->use_image_checkbox && $image ) {
206             $checked = $use_image_checked ? 'checked' : '';
207             $li_inner .= sprintf( '<small><input type="checkbox" value="1" name="%s[_image_flags][%d]" %s /> Use image?</small>', $this->get_form_name(), $post_id, $checked );
208         }
209 
210         $li = $li . apply_filters( 'fieldmanager_draggablepost_li_content', $li_inner, $post_id ) . '</li>';
211         return $li;
212     }
213 
214     /**
215      * Helper to convert the value passed to form_element into a non-hierarchical list of post_ids so we know which posts are already assigned to a bin and thus should be skipped in rendering.
216      * @param array $value as passed to form_element()
217      * @return array containing post_ids in any subarray, except the one attached to key '_image_flags'.
218      */
219     protected function flatten_arrays( $value ) {
220         if ( empty ( $value ) ) {
221             return array();
222         }
223         $result = array();
224         foreach ( $value as $key => $array ) {
225             if ( $key == '_image_flags' ) {
226                 continue;
227             }
228             $result = array_merge( $result, $value[$key] );
229         }
230         $return = array();
231         foreach ( $result as $id ) {
232             if ( $id ) {
233                 $return[] = $id;
234             }
235         }
236         return $return;
237     }
238 }
Fieldmanager API documentation generated by ApiGen 2.8.0