Changeset 1908874
- Timestamp:
- 07/13/2018 04:01:19 PM (6 years ago)
- Location:
- objectives-key-results-okr/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
objectives-key-results-okr/trunk/okr.php
r1907794 r1908874 4 4 Plugin URI: https://mkaion.com/wordpress-okr/ 5 5 Description: WordPress OKR Plugin to manage objectives and key results. 6 Version: 1.0 16 Version: 1.0 7 7 Author: Mainul Kabir Aion 8 8 Author URI: https://mkaion.com/ … … 24 24 */ 25 25 26 add_action('wp_enqueue_scripts','okr_init'); 27 28 function okr_init() { 29 wp_enqueue_script( 'okr', plugins_url( 'assets/js/script.js', __FILE__ )); 30 wp_enqueue_script( 'okr', plugins_url( 'assets/css/style.css', __FILE__ )); 26 add_action('wp_enqueue_scripts', 'okr_init'); 27 28 function okr_init() 29 { 30 wp_enqueue_script('okr', plugins_url('assets/js/script.js', __FILE__)); 31 wp_enqueue_script('okr', plugins_url('assets/css/style.css', __FILE__)); 31 32 } 32 33 33 class OKR { 34 35 const OBJECTIVE_POST_TYPE = 'objective'; 36 const KEY_RESULT_POST_TYPE = 'key_result'; 37 const KEY_RESULT_META_KEY = 'okr_key_result_meta'; 38 39 static function &init() { 40 static $instance = false; 41 42 if ( $instance ) { 43 return $instance; 44 } 45 46 $instance = new OKR; 47 48 return $instance; 49 } 50 51 public function __construct() { 52 53 // Set up the post types. 54 $this->register_objective_post_type(); 55 $this->register_key_result_post_type(); 56 add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) ); 57 add_action( 'wp_insert_post_data', array( $this, 'save_key_result_data' ), 10, 2 ); 58 add_shortcode( 'okr', array( $this, 'shortcode' ) ); 59 60 } 61 62 63 64 65 66 public function add_meta_boxes() { 67 add_meta_box( 'okr_key_result_parent', 'Key Result Data', array( $this, 'add_key_result_meta_box' ), OKR::KEY_RESULT_POST_TYPE ); 68 } 69 70 71 public function add_key_result_meta_box() { 72 global $post; 73 74 wp_nonce_field( 'okr_key_result_data', 'okr_key_result_data' ); 75 $objectives = get_posts( array( 'post_type' => OKR::OBJECTIVE_POST_TYPE ) ); 76 77 $okr_data = get_post_meta( $post->ID, OKR::KEY_RESULT_META_KEY, true ); 78 79 80 echo 'Select Objective'; 81 echo '<select name="key_result_parent">'; 82 echo '<option value="">Choose an Objective</option>'; 83 foreach ( $objectives as $objective ) { 84 echo '<option value="' . (int) $objective->ID . '"' . selected( $objective->ID, $post->post_parent ) . '>' . esc_html ( $objective->post_title ) . '</option>'; 85 } 86 echo '</select>'; 87 echo '<br />'; 88 89 echo 'Due Date:'; 90 echo '<input name="key_result_due_date" type="date" value="' . esc_attr( $okr_data['due_date'] ) . '" />'; 91 echo '<br />'; 92 93 echo 'Percent Complete: '; 94 echo '<input name="key_result_percent_complete" type="number" min="0" max="100" value="' . (int) $okr_data['percent_complete'] . '" />'; 95 echo ' '; 96 97 echo '<div class="range-slider">'; 98 echo ' <input name="key_result_percent_complete" class="range-slider__range" type="range" min="0" max="100" value="' . (int) $okr_data['percent_complete'] . '">'; 99 echo ' <span class="range-slider__value">$okr_data[percent_complete]</span>'; 100 echo '</div>'; 101 102 //echo '<input name="key_result_percent_complete" type="range" min="0" max="100" class="slider" value="' . (int) $okr_data['percent_complete'] . '" />'; 103 104 echo '<br />'; 105 106 echo 'Weight:'; 107 echo '<input name="key_result_weight" type="number" min="0" max="100" value="' . (int) $okr_data['weight'] . '" />'; 108 echo '<br />'; 109 ?> 110 <script type="text/javascript"> 111 var rangeSlider = function(){ 112 var slider = $('.range-slider'), 113 range = $('.range-slider__range'), 114 value = $('.range-slider__value'); 115 116 slider.each(function(){ 117 118 value.each(function(){ 119 var value = " <?php echo $okr_data['percent_complete'] ?>%" ; 120 $(this).html(value); 121 }); 122 123 range.on('input', function(){ 124 $(this).next(value).html(this.value); 125 }); 126 }); 127 }; 128 129 rangeSlider(); 130 </script> 131 <?php 132 133 } 134 135 public function save_key_result_data( $data, $post_array ) { 136 global $post; 137 138 if ( ! wp_verify_nonce( $_POST['okr_key_result_data'], 'okr_key_result_data' ) ) { 139 return $data; 140 } 141 142 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { 143 return $data; 144 } 145 146 if ( OKR::KEY_RESULT_POST_TYPE == $post->post_type ) { 147 $data['post_parent'] = (int) $post_array['key_result_parent']; 148 149 if ( ! isset( $this->key_result_meta ) ) { 150 $this->key_result_meta = array( 151 'due_date' => '', 152 'percent_complete' => 0, 153 'weight' => 1, 154 ); 155 } 156 if ( isset( $post_array['key_result_due_date'] ) && preg_match( '/\d\d\d\d-\d\d-\d\d/', $post_array['key_result_due_date'] ) ) { 157 $this->key_result_meta['due_date'] = sanitize_text_field( $post_array['key_result_due_date'] ); 158 } 159 160 if ( isset( $post_array['key_result_percent_complete'] ) && is_numeric( $post_array['key_result_percent_complete'] ) ) { 161 $this->key_result_meta['percent_complete'] = (int) $post_array['key_result_percent_complete']; 162 } 163 164 if ( isset( $post_array['key_result_weight'] ) && is_numeric( $post_array['key_result_weight'] ) ) { 165 $this->key_result_meta['weight'] = (int) $post_array['key_result_weight']; 166 } 167 168 update_post_meta( $post->ID, OKR::KEY_RESULT_META_KEY, $this->key_result_meta ); 169 } 170 171 return $data; 172 } 173 174 public function shortcode( $attributes ) { 175 $out = ''; 176 177 // Parse the shortcode for an ids or a slugs attribute and fetch the matching Objective ids. 178 $ids = array(); 179 if ( isset( $attributes['slugs'] ) ) { 180 $slugs = explode( ',', $attributes['slugs'] ); 181 foreach( $slugs as $slug ) { 182 $page = get_page_by_path( trim( $slug ), OBJECT, OKR::OBJECTIVE_POST_TYPE ); 183 if ( $page ) { 184 $ids[] = (int) $page->ID; 185 } 186 } 187 } else if ( isset( $attributes['ids'] ) ) { 188 $ids = explode( ',', $attributes['ids'] ); 189 array_walk( $ids, 'trim' ); 190 array_walk( $ids, 'intval' ); 191 } else { 192 return ''; 193 } 194 195 $objectives = get_posts( array( 196 'post_type' => OKR::OBJECTIVE_POST_TYPE, 197 'include' => $ids 198 ) ); 199 200 201 foreach( $objectives as $objective ) { 202 $key_results = get_posts( array( 203 'post_type' => OKR::KEY_RESULT_POST_TYPE, 204 'post_parent' => $objective->ID 205 ) ); 206 $out .= '<div class="objective">'; 207 $out .= '<h3>' . esc_html( $objective->post_title ) . '</h3>'; 208 $out .= '<div class="objective-content">' . esc_html( $objective->post_content ) . '</div>'; 209 210 $weight = 0; 211 $percent_complete = 0; 212 213 foreach ( $key_results as $kr ) { 214 $kr_meta = get_post_meta( $kr->ID, OKR::KEY_RESULT_META_KEY, true ); 215 $out .= '<div class="key-result">'; 216 $out .= '<h4>' . esc_html( $kr->post_title ) . '</h4>'; 217 $out .= '<div class="key-result-content">' . esc_html( $kr->post_content ) . '</div>'; 218 $out .= '<ul class="key-result-meta">'; 219 if ( isset( $kr_meta['due_date'] ) ) { 220 $out .= '<li class="key-result-due-date"><span class="label">' . __( 'Due Date' ) . '</span>' . esc_html( $kr_meta['due_date'] ) . '</li>'; 221 } 222 223 if ( isset( $kr_meta['percent_complete'] ) ) { 224 $out .= '<li class="key-result-percent-complete"><span class="label">' . __( 'Percent Complete' ) . '</span>' . esc_html( $kr_meta['percent_complete'] ) . '</li>'; 225 $percent_complete += (int) $kr_meta['percent_complete']; 226 } 227 228 if ( isset( $kr_meta['weight'] ) ) { 229 $out .= '<li class="key-result-weight"><span class="label">' . __( 'Weight' ) . '</span>' . esc_html( $kr_meta['weight'] ) . '</li>'; 230 $weight += (int) $kr_meta['weight']; 231 } else { 232 $weight += 1; 233 } 234 $out .= '</ul>'; 235 $out .= '</div>'; // .key-result 236 } 237 238 $out .= 'Objective Percent Complete: ' . round( $percent_complete / $weight ) . '%'; 239 $out .= '</div>'; // .objective 240 } 241 242 return $out; 243 } 244 245 private function register_objective_post_type() { 246 247 $labels = array( 248 'name' => 'Objectives', 249 'singular_name' => 'Objective', 250 'menu_name' => 'Objectives', 251 'name_admin_bar' => 'Objectives', 252 'add_new' => 'Add New', 253 'add_new_item' => 'Add New Objective', 254 'new_item' => 'New Objective', 255 'edit_item' => 'Edit Objective', 256 'view_item' => 'View Objective', 257 'all_items' => 'All Objectives', 258 'search_items' => 'Search Objectives', 259 'parent_item_colon' => 'Parent Objectives', 260 'not_found' => 'No Objectives found', 261 'not_found_in_trash' => 'No Objectives found in trash', 262 ); 263 264 $args = array( 265 'labels' => $labels, 266 'public' => true, 267 'publicly_queryable' => true, 268 'show_ui' => true, 269 'show_in_menu' => true, 270 'query_var' => true, 271 'rewrite' => array( 'slug' => 'objective' ), 272 'capability_type' => 'page', 273 'has_archive' => false, 274 'hierarchical' => false, 275 'menu_position' => null, 276 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'comment', 'revisions' ) 277 ); 278 279 register_post_type( OKR::OBJECTIVE_POST_TYPE, $args ); 280 } 281 282 private function register_key_result_post_type() { 283 284 $labels = array( 285 'name' => 'Key Results', 286 'singular_name' => 'Key Result', 287 'menu_name' => 'Key Results', 288 'name_admin_bar' => 'Key Results', 289 'add_new' => 'Add New', 290 'add_new_item' => 'Add New Key Result', 291 'new_item' => 'New Key Result', 292 'edit_item' => 'Edit Key Result', 293 'view_item' => 'View Key Result', 294 'all_items' => 'All Key Results', 295 'search_items' => 'Search Key Results', 296 'parent_item_colon' => 'Parent Key Results', 297 'not_found' => 'No Key Results found', 298 'not_found_in_trash' => 'No Key Result found in trash', 299 ); 300 301 $args = array( 302 'labels' => $labels, 303 'public' => true, 304 'publicly_queryable' => true, 305 'show_ui' => true, 306 'show_in_menu' => true, 307 'query_var' => true, 308 'rewrite' => array( 'slug' => 'key-result' ), 309 'capability_type' => 'page', 310 'has_archive' => false, 311 'hierarchical' => false, 312 'menu_position' => null, 313 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'comment', 'revisions' ), 314 //'register_meta_box_cb' => array( $this, 'add_key_result_meta_box' ), 315 ); 316 317 register_post_type( OKR::KEY_RESULT_POST_TYPE, $args ); 318 } 34 class OKR 35 { 36 37 public function __construct() 38 { 39 add_action( 'init', array( $this, 'register_post_types' ) ); 40 add_action( 'add_meta_boxes', array($this, 'add_meta_boxes' ) ); 41 add_action( 'wp_insert_post_data', array($this, 'save_key_result_data'), 10, 2 ); 42 add_shortcode('okr', array( $this, 'shortcode' ) ); 43 } 44 45 public function add_meta_boxes() 46 { 47 add_meta_box('okr_key_result_parent', 'Key Result Data', array($this, 'add_key_result_meta_box'), 'key_result'); 48 } 49 50 51 public function add_key_result_meta_box() 52 { 53 global $post; 54 55 wp_nonce_field('okr_key_result_data', 'okr_key_result_data'); 56 $objectives = get_posts(array('post_type' => 'objective')); 57 58 $okr_data = array(); 59 60 if ( metadata_exists( 'post', $post->ID, 'okr_key_result_meta' ) ) { 61 $okr_data = get_post_meta($post->ID, 'okr_key_result_meta', true); 62 } else { 63 $okr_data = array_fill_keys( array( 'due_date', 'percent_complete', 'weight' ), '' ); 64 } 65 66 echo '<label> Select Objective </label>'; 67 echo '<select style="margin-left: 20px" name="key_result_parent">'; 68 echo '<option value="">Choose an Objective</option>'; 69 foreach ($objectives as $objective) { 70 echo '<option value="' . (int)$objective->ID . '"' . selected($objective->ID, $post->post_parent) . '>' . esc_html($objective->post_title) . '</option>'; 71 } 72 echo '</select>'; 73 echo '<br />'; 74 75 echo '<label> Due Date:</label>'; 76 echo '<input style="margin-left: 60px" name="key_result_due_date" type="date" value="' . esc_attr($okr_data['due_date']) . '" />'; 77 echo '<br />'; 78 79 echo '<label> Percent Complete: </label>'; 80 echo '<input style="margin-left: 10px" name="key_result_percent_complete" type="number" min="0" max="100" value="' . (int)$okr_data['percent_complete'] . '" />'; 81 echo ' '; 82 83 echo '<div class="range-slider">'; 84 echo ' <input name="key_result_percent_complete" class="range-slider__range" type="range" min="0" max="100" value="' . (int)$okr_data['percent_complete'] . '">'; 85 echo '<span class="range-slider__value">' . $okr_data['percent_complete'] . '</span>'; 86 echo '</div>'; 87 88 //echo '<input name="key_result_percent_complete" type="range" min="0" max="100" class="slider" value="' . (int) $okr_data['percent_complete'] . '" />'; 89 90 echo '<br />'; 91 92 echo '<label>Weight:</label>'; 93 echo '<input style="margin-left: 65px" name="key_result_weight" type="number" min="0" max="100" value="' . (int)$okr_data['weight'] . '" />'; 94 echo '<br />'; 95 ?> 96 <script type="text/javascript"> 97 var rangeSlider = function(){ 98 var slider = $('.range-slider'), 99 range = $('.range-slider__range'), 100 value = $('.range-slider__value'); 101 102 slider.each(function(){ 103 value.each(function(){ 104 var value = " <?php echo $okr_data['percent_complete'] ?>" + " %" ; 105 $(this).html(value); 106 }); 107 range.on('input', function(){ 108 // $('input[name=key_result_percent_complete]').val(this.value); 109 $(this).next(value).html(this.value + '%'); 110 }); 111 }); 112 }; 113 rangeSlider(); 114 </script> 115 <?php 116 117 } 118 119 public function save_key_result_data( $data, $post_array ) 120 { 121 global $post; 122 123 if ( ( isset( $_POST['okr_key_result_data'] ) && !wp_verify_nonce($_POST['okr_key_result_data'], 'okr_key_result_data' ) ) || !isset( $post->ID ) ) { 124 return $data; 125 } 126 127 if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) { 128 return $data; 129 } 130 131 132 if ('key_result' == $post->post_type) { 133 $data['post_parent'] = (int)$post_array['key_result_parent']; 134 135 if (!isset($this->key_result_meta)) { 136 $this->key_result_meta = array( 137 'due_date' => '', 138 'percent_complete' => 0, 139 'weight' => 1, 140 ); 141 } 142 if (isset($post_array['key_result_due_date']) && preg_match('/\d\d\d\d-\d\d-\d\d/', $post_array['key_result_due_date'])) { 143 $this->key_result_meta['due_date'] = sanitize_text_field($post_array['key_result_due_date']); 144 } 145 146 if (isset($post_array['key_result_percent_complete']) && is_numeric($post_array['key_result_percent_complete'])) { 147 $this->key_result_meta['percent_complete'] = (int)$post_array['key_result_percent_complete']; 148 } 149 150 if (isset($post_array['key_result_weight']) && is_numeric($post_array['key_result_weight'])) { 151 $this->key_result_meta['weight'] = (int)$post_array['key_result_weight']; 152 } 153 154 update_post_meta($post->ID, 'okr_key_result_meta', $this->key_result_meta); 155 } 156 157 return $data; 158 } 159 160 public function shortcode($attributes) 161 { 162 $out = ''; 163 164 // Parse the shortcode for an ids or a slugs attribute and fetch the matching Objective ids. 165 $ids = array(); 166 if (isset($attributes['slugs'])) { 167 $slugs = explode(',', $attributes['slugs']); 168 foreach ($slugs as $slug) { 169 $page = get_page_by_path(trim($slug), OBJECT, 'objective'); 170 if ($page) { 171 $ids[] = (int)$page->ID; 172 } 173 } 174 } else if (isset($attributes['ids'])) { 175 $ids = explode(',', $attributes['ids']); 176 array_walk($ids, 'trim'); 177 array_walk($ids, 'intval'); 178 } else { 179 return ''; 180 } 181 182 $objectives = get_posts(array( 183 'post_type' => 'objective', 184 'include' => $ids 185 )); 186 187 188 foreach ($objectives as $objective) { 189 $key_results = get_posts(array( 190 'post_type' => 'key_result', 191 'post_parent' => $objective->ID 192 )); 193 $out .= '<div class="objective">'; 194 $out .= '<h3>' . esc_html($objective->post_title) . '</h3>'; 195 $out .= '<div class="objective-content">' . esc_html($objective->post_content) . '</div>'; 196 197 $weight = 0; 198 $percent_complete = 0; 199 200 foreach ($key_results as $kr) { 201 $kr_meta = get_post_meta($kr->ID, 'okr_key_result_meta', true); 202 $out .= '<div class="key-result">'; 203 $out .= '<h4>' . esc_html($kr->post_title) . '</h4>'; 204 $out .= '<div class="key-result-content">' . esc_html($kr->post_content) . '</div>'; 205 $out .= '<ul class="key-result-meta">'; 206 if (isset($kr_meta['due_date'])) { 207 $out .= '<li class="key-result-due-date"><span class="label">' . __('Due Date') . '</span>' . esc_html($kr_meta['due_date']) . '</li>'; 208 } 209 210 if (isset($kr_meta['percent_complete'])) { 211 $out .= '<li class="key-result-percent-complete"><span class="label">' . __('Percent Complete') . '</span>' . esc_html($kr_meta['percent_complete']) . '</li>'; 212 $percent_complete += (int)$kr_meta['percent_complete']; 213 } 214 215 if (isset($kr_meta['weight'])) { 216 $out .= '<li class="key-result-weight"><span class="label">' . __('Weight') . '</span>' . esc_html($kr_meta['weight']) . '</li>'; 217 $weight += (int)$kr_meta['weight']; 218 } else { 219 $weight += 1; 220 } 221 $out .= '</ul>'; 222 $out .= '</div>'; // .key-result 223 } 224 225 $out .= 'Objective Percent Complete: ' . round($percent_complete / $weight) . '%'; 226 $out .= '</div>'; // .objective 227 } 228 229 return $out; 230 } 231 232 public function register_post_types() { 233 234 $labels = array( 235 'name' => 'Objectives', 236 'singular_name' => 'Objective', 237 'menu_name' => 'Objectives', 238 'name_admin_bar' => 'Objective', 239 'archives' => 'Objective Archives', 240 'attributes' => 'Objective Attributes', 241 'parent_item_colon' => 'Parent Objective:', 242 'all_items' => 'All Objectives', 243 'add_new_item' => 'Add New Objective', 244 'add_new' => 'Add New', 245 'new_item' => 'New Objective', 246 'edit_item' => 'Edit Objective', 247 'update_item' => 'Update Objective', 248 'view_item' => 'View Objective', 249 'view_items' => 'View Objectives', 250 'search_items' => 'Search Objective', 251 'not_found' => 'Not found', 252 'not_found_in_trash' => 'Not found in Trash', 253 'featured_image' => 'Featured Image', 254 'set_featured_image' => 'Set featured image', 255 'remove_featured_image' => 'Remove featured image', 256 'use_featured_image' => 'Use as featured image', 257 'uploaded_to_this_item' => 'Uploaded to this item', 258 'items_list' => 'Objectives list', 259 'items_list_navigation' => 'Objectives list navigation', 260 'filter_items_list' => 'Filter Objectives list', 261 ); 262 $args = array( 263 'label' => 'Objective', 264 'description' => 'Post Type Description', 265 'labels' => $labels, 266 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'comments' ), 267 'taxonomies' => array( 'category' ), 268 'hierarchical' => false, 269 'public' => true, 270 'show_ui' => true, 271 'show_in_menu' => true, 272 'menu_position' => 5, 273 'show_in_admin_bar' => true, 274 'show_in_nav_menus' => true, 275 'can_export' => true, 276 'has_archive' => true, 277 'exclude_from_search' => false, 278 'publicly_queryable' => true, 279 'capability_type' => 'page', 280 ); 281 register_post_type( 'objective', $args ); 282 283 $labels = array( 284 'name' => 'Key Results', 285 'singular_name' => 'Key Result', 286 'menu_name' => 'Key Results', 287 'name_admin_bar' => 'Key Result', 288 'archives' => 'Key Result Archives', 289 'attributes' => 'Key Result Attributes', 290 'parent_item_colon' => 'Parent Key Result:', 291 'all_items' => 'All Key Results', 292 'add_new_item' => 'Add New Key Result', 293 'add_new' => 'Add New', 294 'new_item' => 'New Key Result', 295 'edit_item' => 'Edit Key Result', 296 'update_item' => 'Update Key Result', 297 'view_item' => 'View Key Result', 298 'view_items' => 'View Key Results', 299 'search_items' => 'Search Key Result', 300 'not_found' => 'Not found', 301 'not_found_in_trash' => 'Not found in Trash', 302 'featured_image' => 'Featured Image', 303 'set_featured_image' => 'Set featured image', 304 'remove_featured_image' => 'Remove featured image', 305 'use_featured_image' => 'Use as featured image', 306 'uploaded_to_this_item' => 'Uploaded to this item', 307 'items_list' => 'Key Results list', 308 'items_list_navigation' => 'Key Results list navigation', 309 'filter_items_list' => 'Filter Key Results list', 310 ); 311 312 $args = array( 313 'label' => 'Key Result', 314 'description' => 'Post Type Description', 315 'labels' => $labels, 316 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'comments' ), 317 'taxonomies' => array( 'category' ), 318 'hierarchical' => false, 319 'public' => true, 320 'show_ui' => true, 321 'show_in_menu' => true, 322 'menu_position' => 6, 323 'show_in_admin_bar' => true, 324 'show_in_nav_menus' => true, 325 'can_export' => true, 326 'has_archive' => true, 327 'exclude_from_search' => false, 328 'publicly_queryable' => true, 329 'capability_type' => 'page', 330 ); 331 register_post_type( 'key_result', $args ); 332 333 } 334 319 335 } 320 336 321 add_action( 'init', array( 'OKR', 'init' ) ); 322 337 new OKR(); 338 339 340 -
objectives-key-results-okr/trunk/readme.txt
r1907822 r1908874 4 4 Tags: tasks, objectives, goals, okr 5 5 Requires at least: 4.0 6 Tested up to: 4. 86 Tested up to: 4. 7 7 Stable tag: trunk 8 8 Requires PHP: 5.4 … … 62 62 63 63 == Changelog == 64 11.7.201864 2018 65 65 * Initial Release 66 66 67 68 69 67 70 71
Note: See TracChangeset
for help on using the changeset viewer.