-
-
Save HenriqueSilverio/e2f46d7831b792b7e6ce0f1ad6bbd121 to your computer and use it in GitHub Desktop.
<?php | |
namespace MyPlugin\Contracts; | |
interface Shortcode | |
{ | |
public function getTag(): string; | |
public function start(): void; | |
public function register(): void; | |
public function render($atts = '', ?string $content, string $tag): string; | |
} |
<?php | |
namespace MyPlugin\Shortcodes; | |
use MyPlugin\Contracts\Shortcode as iShortcode; | |
abstract class Shortcode implements iShortcode | |
{ | |
private $tag = ''; | |
public function __construct(string $tag) | |
{ | |
$this->tag = $tag; | |
} | |
public function getTag(): string | |
{ | |
return $this->tag; | |
} | |
public function start(): void | |
{ | |
$this->register(); | |
} | |
public function register(): void | |
{ | |
add_shortcode( | |
'myprefix_' . $this->getTag(), | |
[$this, 'render'] | |
); | |
} | |
} |
<?php | |
namespace MyPlugin\Shortcodes; | |
use MyPlugin\Shortcodes\Shortcode; | |
class Login extends Shortcode | |
{ | |
public function render($atts = '', ?string $content, string $tag): string | |
{ | |
return 'Shortcode content here!'; | |
} | |
} |
<?php | |
namespace MyPlugin; | |
use MyPlugin\Shortcodes\Login; | |
class Plugin | |
{ | |
public function start(): void | |
{ | |
$shortcodeLogin = new Login('form_login'); | |
$shortcodeLogin->start(); | |
} | |
} |
<?php | |
use MyPlugin\Plugin; | |
require_once 'vendor/autoload.php'; | |
$plugin = new Plugin(); | |
add_action('plugins_loaded', [$plugin, 'start']); |
Hey @carlalexander, thanks for your comment! Yeah, I'll add the doc blocks soon.
For now, Iet's see if I can clarify your question, and if I'm in the "right path" or it's unnecessary.
What is the purpose of the start and register methods?
The idea of these methods is follow an kind of "Facade" pattern, like described here.
Thinking in context of an plugin a little bit "bigger" than just creating one shortcode, "catch"?
What I noticed is that, generally, I have methods like start
and register
in objects which hooks into WordPress.
So maybe, I can have one other interface like... Hookable
with it. Anyway...
And the main Plugin
class has a start
method, where it'll start
all the others components later.
Then the Plugin::start
could be splited in something like startPublic
, startAdmin
, etc, according to "project specific" requirements.
So... Could I clarify? Think you this make more sense now? 🤔
This is a great starting point :). I'd add a few notes to Carl's. They are more of less a listing of things that I notice off the bat and are my no means meant to be the way to refactor anything. Just points for consideration.
private $tag = '';
could probably (or perhaps should probably) beprotected
unless any subclass will never overwrite it.?string $content
: Would this ever not be a string? I don't mean that I don't get why you did it, but I'm wondering if it needs to be simply strictly typed asstring
or not.- It looks like you can use
register
and removestart
and put all of the logic there. - I would not hardcode
'myprefix_'
- Nice use of type hinting, namespaces, and shortcodes on arrays - nice to see some modern features here 👍
Thanks for bringing this to our attention and keep up the good work :).
Hi Tom, thanks for your feedback too!
?string $content
: Would this ever not be a string?
I've used nullable type here, because the shortcode content sometimes could be null
.
So maybe if we strictly type it as string
, probably will conflict in this cases. 🤔
Again, thank you guys for the opinions. (@carlalexander, @tommcfarlin).
I really appreciate your efforts to bring attention to good practices and modern PHP on the WordPress community! 🤘
So this looks pretty good! The main thing that I noticed is:
Right now, the
start
method calls theregister
method and yourPlugin
class calls thestart
method. But you could do achieve all of this by just usingregister
everywhere. That said, I might misunderstand the purpose of thestart
method because there's no doc block in youriShortcode
interface.It might be worth while for you to write documentation for it. This is super important for interfaces since they're just a contract without any code. It'll also help you clarify the purpose of each method. You might even realize that you didn't need both the
start
andregister
method. 😃