0

I have this class that generates some share links:

<?php

class Post_Share {
    /**
    * Class to add post-sharing capabilities to each post. It has to be initialized within a post page.
    */

    function __construct( $networks = array(), $post, $style, $display_it ) {
        /**
        * Consturctor for the Post_Share class.
        * @param $networks      What networks we want the post to be shared on.
        * @param $post          The post itself.
        * @param $style         Which style the sharer should have.
        * @see .share-style-2 in style.css to see what available styles we have.
        */
        $this->networks         = $networks;
        $this->post             = $post;
        $this->style            = $style;
        $this->display_it       = $display_it;
    }

    private function generate_social_output() {
        /**
        * Function to build the social share links. The way it works is we keep adding onto an "output" based
        * on user input.
        */
        $output = '';

        foreach( $this->networks as $network ) {
            /** 
            * @see An if-if-if logic was chosen due to the fact that the script should continue if a past condition * as not met. The way it works now is "if past condition is not met, skip, verify this one."
            */
            if( $network == 'facebook' ) {
                $output .= '<a class="facebook-share share-post-icon" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=' . get_permalink() . '"><i class="sf-1"></i></a>';
            }

            if( $network == 'twitter' ) {
                $output .= '<a class="twitter-share share-post-icon" target="_blank" href="https://twitter.com/home?status=Check%20out%20this%20article:%20' . get_permalink() . '%20-%20' . '"><i class="sf-6"></i></a>';
            }

            if( $network == 'pinterest' ) {
                $image = wp_get_attachment_url( get_post_thumbnail_id( $this->post->ID ) );
                $output .= '<a class="pinterest-share share-post-icon" target="_blank" href="https://pinterest.com/pin/create/button/?url=' . get_permalink() . '&media=' . $image . '&description=' . get_the_title() . '"><i class="sf-5"></i></a>';
            }

            if( $network == 'gplus' ) {
                $output .= '<a class="gplus-share share-post-icon" target="_blank" href="https://plus.google.com/share?url=' . get_permalink() . '"><i class="sf-3"></i></a>';
            }
        }

        return $output;
    }

    public function generate_share_links() {
        /**
        * This function ultimately generates the sharer class itself, using data ingested from *generate_social_output.
        */

        $networks_el = array_intersect( array( 'facebook', 'twitter', 'pinterest', 'gplus' ), $this->networks );

        if( empty( $networks_el ) ) {
            return new WP_Error( 'empty_networks', esc_html__( 'No networks were set up.', '_s') );
        } else {

            if ( is_single() ) {
                $output = '<div class="post-share ' . $this->style . '">' . '<div class="holder">';
                $output .= $this->generate_social_output();
                $output .= '</div></div>';

                if ( 'yes' == $this->display_it ) {
                    echo $output;
                } else {
                    return $output;
                }

            } else if ( !is_single() && $this->style == 'share-style-1' ) {
                // If we're not on the post page and the style is '1', then we know that we should display the share buttons somewhere else, e.g: Homepage.
                $output = '<div class="post-share share-style-1"><div class="holder">';
                $output .= $this->generate_social_output();
                $output .= '</div></div>';

                if ( 'yes' == $this->display_it ) {
                    echo $output;
                } else {
                    return $output;
                }
            }
        }
    }
}

The way I call it, within my post page:

<?php
    (new Post_Share( array( 'facebook', 'twitter', 'gplus', 'pinterest' ), $post, $style = 'share-style-2', $display_it = 'yes' ))->generate_share_links();
    ?>

Is rather...arcane, here's the full thing:

<article id="single-post-<?php the_ID(); ?>" <?php post_class('single-post'); ?>>
    <?php
    (new Post_Share( array( 'facebook', 'twitter', 'gplus', 'pinterest' ), $post, $style = 'share-style-2', $display_it = 'yes' ))->generate_share_links();
    ?>
    <header class="single-post-header">
        <div class="single-post-meta">
            <?php echo _s_show_post_info( array( 'author','time', 'category' ) ); ?>
        </div><!-- .post-meta -->

        <?php
        the_title( '<h1 class="single-post-title">','</h1>' );
        if ( has_category() ) : ?>
            <?php

            $categories = (array) wp_get_post_terms( get_the_ID(), 'category' );

            if ( !is_wp_error( $categories ) && !empty( $categories) ) { ?>
                <div class="single-post-secondary-meta">
                    <span class="single-post-category-span">posted in
                        <a class="single-post-category" href="<?php echo get_term_link( $categories[0] )?>"><?php echo $categories[0] -> name ?>
                        </a>
                    </span>
                </div><!-- .post-meta-2 -->
            <?php } ?>
        <?php endif; ?>
    </header><!-- .post-header -->

    <?php if ( has_post_thumbnail() ) : ?>
        <?php if ( !has_post_format( $format = array( 'video', 'audio') ) ) : ?>
            <div class="single-post-thumbnail">
                <a class="single-post-thumbnail-link" href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
                    <?php the_post_thumbnail(); ?>
                </a>
            </div><!-- .post-thumbnail -->
        <?php endif; ?>
    <?php endif; ?>

    <div class="single-post-content">
        <?php
            //echo wp_trim_words( get_the_content(), 40, '...' );
            the_content();
        ?>
    </div><!-- .post-content -->
</article><!-- #post-<?php the_ID(); ?> -->
<?php 
get_template_part('template-parts/individual_post-related-posts');
?>

How could I better initialize it?

I'm looking for:

  • Not using a variable to initialize only the class, then do a -> call to the generate_share_links.

  • Not using the double brackets from (new .. .. )->.

What are my choices here?

1

You can avoid using (new ...)-> by using a static method, which creates the new instance internally.

Combining this with the magic __toString method allows you to directly echo the created instance.

Here is how to write it:

<?php
class Post_Share {
    /**
     * Using Post_Share::generate() will directly return the new instance,
     * so (new Post_Share) is not needed.
     */
    public static function generate( $networks = array(), $post, $style, $display = 'no' ) {
        return new self( $networks, $post, $style, $display );
    }

    /**
     * Calling additional methods can be avoided by echoing the instance.
     */
    public function __toString() {
        // Backup
        $original_display = $this->display_it;
        $this->display_it = false;

        // Generate
        $output = $this->generate_share_links();

        // Restore
        $this->display_it = $original_display;

        return $output;
    }

    // ...your own code
}

Once you do it this way, you can do both of these:

<?php Post_Share::generate( array( 'facebook' ), $post, 'share-style-2' )->generate_share_links() ?>

and

<?php echo Post_Share::generate( array( 'facebook' ), $post, 'share-style-2' ) ?>

There are a few things happening here:

  1. The static keyword in the first method means that you do not need to create an instance of the class in order to call the method, you just call the class name, followed by double colons and then the method name (ex. Post_share::generate).
  2. The self keyword refers to the name of the current class. new self is equal to new Post_Share.
  3. By using the static method, you can avoid having to wrap the class instantiation with brackets, so no (new ...).
  4. The __toString method is called automatically once PHP attempts to transform the class to a string. This happens when echoing the class (like in the example), concatenating it (`Post_Share::generate(...) . ' more text') and etc.
  • This works, but, damn, what happened in here? Can you explain a bit in detail why this works? – Jonathan Guerin Jan 10 '18 at 20:12
  • I added some details to the end of the answer. – Radoslav Georgiev Jan 10 '18 at 20:18
  • Thank you! I assume the __toString() and the need to play with $display_it is because I choose to echo or not and that affects how __toString() would handle it, right? Can you elaborate a bit? – Jonathan Guerin Jan 10 '18 at 20:38
  • Yes, exactly. __toString() must never have any output and must just return the newly generated string. I am backing up the existing $display_it variable, in order to ensure that the generate_share_links method will not have any output, then restoring it. In general, since we are implementing the __toString functionality, I would suggest completely removing the display flag altogether from the code. – Radoslav Georgiev Jan 10 '18 at 20:40
  • Glad to help. Don't forget to mark the answer as correct if you find it sufficient – Radoslav Georgiev Jan 10 '18 at 20:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.