Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like SAL_Post often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use SAL_Post, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 14 | abstract class SAL_Post { |
||
| 15 | public $post; |
||
| 16 | public $context; |
||
| 17 | public $site; |
||
| 18 | |||
| 19 | function __construct( $site, $post, $context ) { |
||
| 24 | |||
| 25 | public function __set( $key, $value ) { |
||
| 28 | |||
| 29 | public function __get( $key ) { |
||
| 36 | |||
| 37 | public function __call( $name, $arguments ) { |
||
| 44 | |||
| 45 | public function __isset ( $name ) { |
||
| 48 | |||
| 49 | abstract public function get_like_count(); |
||
| 55 | |||
| 56 | public function get_menu_order() { |
||
| 59 | |||
| 60 | public function get_guid() { |
||
| 63 | |||
| 64 | public function get_type() { |
||
| 67 | |||
| 68 | public function get_terms() { |
||
| 89 | |||
| 90 | public function get_tags() { |
||
| 91 | $tags = array(); |
||
| 92 | $terms = wp_get_post_tags( $this->post->ID ); |
||
| 93 | foreach ( $terms as $term ) { |
||
| 94 | if ( !empty( $term->name ) ) { |
||
| 95 | $tags[$term->name] = $this->format_taxonomy( $term, 'post_tag', 'display' ); |
||
| 96 | } |
||
| 97 | } |
||
| 98 | return (object) $tags; |
||
| 99 | } |
||
| 100 | |||
| 101 | public function get_categories() { |
||
| 102 | $categories = array(); |
||
| 103 | $terms = wp_get_object_terms( $this->post->ID, 'category', array( 'fields' => 'all' ) ); |
||
| 104 | View Code Duplication | foreach ( $terms as $term ) { |
|
| 105 | if ( !empty( $term->name ) ) { |
||
| 106 | $categories[$term->name] = $this->format_taxonomy( $term, 'category', 'display' ); |
||
| 107 | } |
||
| 108 | } |
||
| 109 | return (object) $categories; |
||
| 110 | } |
||
| 111 | |||
| 112 | public function get_attachments_and_count() { |
||
| 113 | $attachments = array(); |
||
| 114 | $_attachments = new WP_Query( array( 'post_parent' => $this->post->ID, 'post_status' => 'inherit', 'post_type' => 'attachment', 'posts_per_page' => '20' ) ); |
||
| 115 | foreach ( $_attachments->posts as $attachment ) { |
||
| 116 | $attachments[$attachment->ID] = $this->get_media_item_v1_1( $attachment->ID ); |
||
| 117 | } |
||
| 118 | return array( (object) $attachments, (int) $_attachments->found_posts ); |
||
| 119 | } |
||
| 120 | |||
| 121 | public function get_metadata() { |
||
| 122 | $metadata = array(); |
||
| 123 | foreach ( (array) has_meta( $this->post->ID ) as $meta ) { |
||
| 124 | // Don't expose protected fields. |
||
| 125 | $meta_key = $meta['meta_key']; |
||
| 126 | |||
| 127 | $show = !( WPCOM_JSON_API_Metadata::is_internal_only( $meta_key ) ) |
||
| 128 | && |
||
| 129 | ( |
||
| 130 | WPCOM_JSON_API_Metadata::is_public( $meta_key ) |
||
| 131 | || |
||
| 132 | current_user_can( 'edit_post_meta', $this->post->ID , $meta_key ) |
||
| 133 | ); |
||
| 134 | |||
| 135 | if ( $show ) { |
||
| 136 | $metadata[] = array( |
||
| 137 | 'id' => $meta['meta_id'], |
||
| 138 | 'key' => $meta['meta_key'], |
||
| 139 | 'value' => maybe_unserialize( $meta['meta_value'] ), |
||
| 140 | ); |
||
| 141 | } |
||
| 142 | } |
||
| 143 | |||
| 144 | if ( ! empty( $metadata ) ) { |
||
| 145 | return $metadata; |
||
| 146 | } else { |
||
| 147 | return false; |
||
| 148 | } |
||
| 149 | } |
||
| 150 | |||
| 151 | public function get_meta() { |
||
| 152 | $meta = (object) array( |
||
| 153 | 'links' => (object) array( |
||
| 154 | 'self' => (string) $this->get_post_link(), |
||
| 155 | 'help' => (string) $this->get_post_link( 'help' ), |
||
| 156 | 'site' => (string) $this->get_site_link(), |
||
| 157 | 'replies' => (string) $this->get_post_link( 'replies/' ), |
||
| 158 | 'likes' => (string) $this->get_post_link( 'likes/' ), |
||
| 159 | ), |
||
| 160 | ); |
||
| 161 | |||
| 162 | // add autosave link if a more recent autosave exists |
||
| 163 | if ( 'edit' === $this->context ) { |
||
| 164 | $autosave = wp_get_post_autosave( $this->post->ID ); |
||
| 165 | if ( $autosave && $autosave->post_modified > $this->post->post_modified ) |
||
| 166 | $meta->links->autosave = (string) $this->get_post_link() . '/autosave'; |
||
| 167 | } |
||
| 168 | |||
| 169 | return $meta; |
||
| 170 | } |
||
| 171 | |||
| 172 | public function get_current_user_capabilities() { |
||
| 173 | return array( |
||
| 174 | 'publish_post' => current_user_can( 'publish_post', $this->post ), |
||
| 175 | 'delete_post' => current_user_can( 'delete_post', $this->post ), |
||
| 176 | 'edit_post' => current_user_can( 'edit_post', $this->post ) |
||
| 177 | ); |
||
| 178 | } |
||
| 179 | |||
| 180 | public function get_revisions() { |
||
| 181 | if ( 'edit' !== $this->context ) { |
||
| 182 | return false; |
||
| 183 | } |
||
| 184 | |||
| 185 | $revisions = array(); |
||
| 186 | $post_revisions = wp_get_post_revisions( $this->post->ID ); |
||
| 187 | |||
| 188 | foreach ( $post_revisions as $_post ) { |
||
| 189 | $revisions[] = $_post->ID; |
||
| 190 | } |
||
| 191 | |||
| 192 | return $revisions; |
||
| 193 | } |
||
| 194 | |||
| 195 | public function get_other_urls() { |
||
| 196 | $other_urls = array(); |
||
| 197 | |||
| 198 | if ( 'publish' !== $this->post->post_status ) { |
||
| 199 | $other_urls = $this->get_permalink_suggestions( $this->post->post_title ); |
||
| 200 | } |
||
| 201 | |||
| 202 | return (object) $other_urls; |
||
| 203 | } |
||
| 204 | |||
| 205 | protected function get_site_link() { |
||
| 206 | return $this->links->get_site_link( $this->site->get_id() ); |
||
|
|
|||
| 207 | } |
||
| 208 | |||
| 209 | protected function get_post_link( $path = null ) { |
||
| 210 | return $this->links->get_post_link( $this->site->get_id(), $this->post->ID, $path ); |
||
| 211 | } |
||
| 212 | |||
| 213 | public function get_publicize_urls() { |
||
| 214 | $publicize_URLs = array(); |
||
| 215 | $publicize = get_post_meta( $this->post->ID, 'publicize_results', true ); |
||
| 216 | View Code Duplication | if ( $publicize ) { |
|
| 217 | foreach ( $publicize as $service => $data ) { |
||
| 218 | switch ( $service ) { |
||
| 219 | case 'twitter' : |
||
| 220 | foreach ( $data as $datum ) { |
||
| 221 | $publicize_URLs[] = esc_url_raw( "https://twitter.com/{$datum['user_id']}/status/{$datum['post_id']}" ); |
||
| 222 | } |
||
| 223 | break; |
||
| 224 | case 'fb' : |
||
| 225 | foreach ( $data as $datum ) { |
||
| 226 | $publicize_URLs[] = esc_url_raw( "https://www.facebook.com/permalink.php?story_fbid={$datum['post_id']}&id={$datum['user_id']}" ); |
||
| 227 | } |
||
| 228 | break; |
||
| 229 | } |
||
| 230 | } |
||
| 231 | } |
||
| 232 | return (array) $publicize_URLs; |
||
| 233 | } |
||
| 234 | |||
| 235 | public function get_page_template() { |
||
| 236 | return (string) get_post_meta( $this->post->ID, '_wp_page_template', true ); |
||
| 237 | } |
||
| 238 | |||
| 239 | // note this is overridden in jetpack-shadow |
||
| 240 | public function get_featured_image() { |
||
| 241 | $image_attributes = wp_get_attachment_image_src( get_post_thumbnail_id( $this->post->ID ), 'full' ); |
||
| 242 | if ( is_array( $image_attributes ) && isset( $image_attributes[0] ) ) { |
||
| 243 | return (string) $image_attributes[0]; |
||
| 244 | } else { |
||
| 245 | return ''; |
||
| 246 | } |
||
| 247 | } |
||
| 248 | |||
| 249 | public function get_post_thumbnail() { |
||
| 250 | $thumb = null; |
||
| 251 | |||
| 252 | $thumb_id = get_post_thumbnail_id( $this->post->ID ); |
||
| 253 | |||
| 254 | View Code Duplication | if ( ! empty( $thumb_id ) ) { |
|
| 255 | $attachment = get_post( $thumb_id ); |
||
| 256 | if ( ! empty( $attachment ) ) |
||
| 257 | $featured_image_object = $this->get_attachment( $attachment ); |
||
| 258 | |||
| 259 | if ( ! empty( $featured_image_object ) ) { |
||
| 260 | $thumb = (object) $featured_image_object; |
||
| 261 | } |
||
| 262 | } |
||
| 263 | |||
| 264 | return $thumb; |
||
| 265 | } |
||
| 266 | |||
| 267 | public function get_format() { |
||
| 268 | $format = (string) get_post_format( $this->post->ID ); |
||
| 269 | if ( !$format ) { |
||
| 270 | $format = 'standard'; |
||
| 271 | } |
||
| 272 | |||
| 273 | return $format; |
||
| 274 | } |
||
| 275 | |||
| 276 | View Code Duplication | private function get_attachment( $attachment ) { |
|
| 295 | |||
| 296 | public function get_date() { |
||
| 297 | return (string) WPCOM_JSON_API_Date::format_date( $this->post->post_date_gmt, $this->post->post_date ); |
||
| 298 | } |
||
| 299 | |||
| 300 | public function get_modified_date() { |
||
| 301 | return (string) WPCOM_JSON_API_Date::format_date( $this->post->post_modified_gmt, $this->post->post_modified ); |
||
| 302 | } |
||
| 303 | |||
| 304 | public function get_title() { |
||
| 305 | if ( 'display' === $this->context ) { |
||
| 306 | return (string) get_the_title( $this->post->ID ); |
||
| 307 | } else { |
||
| 308 | return (string) htmlspecialchars_decode( $this->post->post_title, ENT_QUOTES ); |
||
| 309 | } |
||
| 310 | } |
||
| 311 | |||
| 312 | public function get_url() { |
||
| 313 | if ( 'revision' === $this->post->post_type ) { |
||
| 319 | |||
| 320 | public function get_shortlink() { |
||
| 323 | |||
| 324 | public function get_content() { |
||
| 335 | |||
| 336 | public function get_excerpt() { |
||
| 348 | |||
| 349 | public function get_status() { |
||
| 352 | |||
| 353 | public function is_sticky() { |
||
| 356 | |||
| 357 | public function get_slug() { |
||
| 360 | |||
| 361 | public function get_password() { |
||
| 368 | |||
| 369 | public function get_parent() { |
||
| 387 | |||
| 388 | function the_password_form() { |
||
| 391 | |||
| 392 | public function get_discussion() { |
||
| 401 | |||
| 402 | public function is_likes_enabled() { |
||
| 412 | |||
| 413 | public function is_sharing_enabled() { |
||
| 425 | |||
| 426 | // No Blog ID parameter. No Post ID parameter. Depends on globals. |
||
| 427 | // Expects setup_postdata() to already have been run |
||
| 428 | View Code Duplication | function get_the_post_content_for_display() { |
|
| 448 | |||
| 449 | public function get_author() { |
||
| 492 | |||
| 493 | protected abstract function get_avatar_url( $email, $avatar_size = 96 ); |
||
| 494 | |||
| 495 | /** |
||
| 496 | * Get extra post permalink suggestions |
||
| 497 | * @return array array of permalink suggestions: 'permalink_URL', 'suggested_slug' |
||
| 498 | */ |
||
| 499 | public function get_permalink_suggestions( $title ) { |
||
| 504 | |||
| 505 | View Code Duplication | private function format_taxonomy( $taxonomy, $taxonomy_type, $context ) { |
|
| 543 | |||
| 544 | // TODO: factor this out into site |
||
| 545 | View Code Duplication | private function get_media_item_v1_1( $media_id ) { |
|
| 667 | } |
||
| 668 |
Since your code implements the magic getter
_get, this function will be called for any read access on an undefined variable. You can add the@propertyannotation to your class or interface to document the existence of this variable.If the property has read access only, you can use the @property-read annotation instead.
Of course, you may also just have mistyped another name, in which case you should fix the error.
See also the PhpDoc documentation for @property.