0

Currently I'm working on a plugin that will display a grid based on post type with many settings to customize it. One of the settings will be to choose between different skins available to display inside the grid.

I would like to offer the possibility to developers to include their own skins with a custom HOOK/Filter.

What is the right way to add this functionality in a plugin?

I was thinking about something like this but I'm not sure if it's the right way and if it will work:

// register skin class in plugin
class skinclass {
    //existing skins
    function myclass() {

    }
    do_action('add_custom_skin');
}

// developers register action to include it's own skins (in function.php)
add_action('add_custom_skin','my_custom_skins')
function my_custom_skins($post) {

    function skin1($post) {
        $skin1  = '<article class="skin1-holder">';
        $skin1 .= '<h2 class="skin1-title">'. get_the_title() .'</h2>';
        $skin1 .= '<div class="skin1-excerpt">'. get_the_excerpt() .'</div>';
        $skin1 .= '</article>';
        return $skin1;
    }

    function skin2($post) {
        $skin2  = '<article class="skin2-holder">';
        $skin2 .= '<h2 class="skin2-title">'. get_the_title() .'</h2>';
        $skin2 .= '<div class="skin2-excerpt">'. get_the_excerpt() .'</div>';
        $skin2 .= '</article>';
        return $skin2;
    }

}

// get skin function in plugin
$skins = get_class_methods(new skinclass());
// to output skin in a drop down list
foreach ($skins as $skin_name) {
    echo "$skin_name\n";
}

// output skin in front end
$func = 'skin1';
$func();

The skin to output will be in a query_posts loop.

2 Answers 2

1
+50

You cannot insert the do_action() inside the class like that, it's gonna give you a fatal error.

Instead you could use an array $skins to store all the skin functions (as closures), and the magic method _call() to call them:

class skinclass {

    private $skins = array();

    function __construct() {
        $this->skins = apply_filters( 'add_skin', $this->skins );
    }

    function __call( $name, $post ) {
        if(isset($this->skins[$name]))
            return $this->skins[$name]( $post );
    }

}

As you can see I used apply_filters() to be able to add skins on initializazion, and then the__call is gonna check if the skin exists and, if so, execute it.

So now to add a skin you add a filter that modifies the $skins property:

// add skin1
add_filter( 'add_skin', function( $skins ){
    $skins['skin1'] = function( $post ) {
        $skin1  = '<article class="skin1-holder">';
        $skin1 .= '<h2 class="skin1-title">'. get_the_title() .'</h2>';
        $skin1 .= '<div class="skin1-excerpt">'. get_the_excerpt() .'</div>';
        $skin1 .= '</article>';
        return $skin1;
    };
    return $skins;
});

// add skin2
add_filter( 'add_skin', function( $skins ){
    $skins['skin2'] = function( $post ) {
        $skin2  = '<article class="skin2-holder">';
        $skin2 .= '<h2 class="skin2-title">'. get_the_title() .'</h2>';
        $skin2 .= '<div class="skin2-excerpt">'. get_the_excerpt() .'</div>';
        $skin2 .= '</article>';
        return $skin2;
    };
    return $skins;
});

Wait, but what about retrieving the skins list? Well, we can add a method to the class to do that, so inside the class you can add:

function get_skins() {
    return array_keys($this->skins);
}

Ok so now to use the class you need to get an instance:

$skinObj = new skinclass();

And the rest is very similar to your code:

// get skin function in plugin
$skins = $skinObj->get_skins();
// to output skin in a drop down list
foreach ($skins as $skin_name) {
    echo "$skin_name\n";
}

// output skin in front end
$func = 'skin1';
echo $skinObj->$func( $post );
1

I understand, that you add the possibilties for developers to change the html, typical a template part. That is the point, that I think you should use the default functionality for this job. get_page_template() can be overridden via the page_template filter.

A simple example for the dev to change your templates from your plugin.

add_filter( 'page_template', 'wpse185512_page_template' );
function wpse185512_page_template( $page_template ) {

    if ( is_page( 'my-custom-page-slug' ) ) {
        $page_template = dirname( __FILE__ ) . '/custom-page-template.php';
    }

    return $page_template;
}

For the include in your plugin use a custom function, that include the file from a path. You find a good reference on this question. I think is not helpful to copy this here, much better you see the answers and understand the solutions.

5
  • Thank you for your answer but it doesn't correspond to my need. My aim is not to modify a template by to add a complete markup from nothing.
    – freaky
    May 4, 2015 at 10:54
  • The content of the template define you as developer, like a header.php of a theme have also only a part of a result.
    – bueltge
    May 4, 2015 at 12:37
  • So, in your answer I can't see how to implement it...
    – freaky
    May 4, 2015 at 12:39
  • The last paragraph link to a question, there have fine answers to how to implement in plugins. Do you have read this?
    – bueltge
    May 5, 2015 at 9:13
  • Yes I have read it. But I still think that it doesn't correspond to my need... I want to add skin to style post in a loop. Not to change a template...
    – freaky
    May 5, 2015 at 9:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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