Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Components/Parsers #104

Closed
mattrabe opened this issue Jan 7, 2019 · 2 comments
Closed

Custom Components/Parsers #104

mattrabe opened this issue Jan 7, 2019 · 2 comments
Labels
idea New feature or request

Comments

@mattrabe
Copy link

mattrabe commented Jan 7, 2019

This ticket addresses the concept of allowing custom, extensible "markup" to be added to the body of a post, and then parse it in a controller method created by the dev. In my initial implementation I am using JSON format for the "markup". For example, adding {{ OGBadge: http://completecodesolutions.com }} to a post body will result in a controller method firing that pulls OG data from that URL, and returns some HTML that displays the retrieved data. The idea is that devs could use their own tags such as {{ Anything: "red" }} or {{ SomethingElse: { "color": "blue" } }} and then create Controller methods parseAnything() or parseSomethingElse that return some custom dynamic markup.

Background: I'm starting a blog using Wink, and in one of my first posts I wanted to display a link out to another site. I figured using the OpenGraph data that the external site provides in its header would be a great choice. I found a nice package to retrieve and parse the OG data. But then what? How can I get a dynamic blog post to somehow utilize this package and return a "badge" with the og data retrieved from the external site? Not seeing an existing way to do that, I thought "how about allowing custom markup in the post body, which is then parsed by a custom method on my BlogController."

As a side note, I'm sure there is a better term for this than "custom markup"... "Custom tags" was my first thought, but "tags" conflicts with the existing feature. Perhaps "custom component."

Here is my initial implementation. I have a model at App\WinkPost that extends \Wink\WinkPost. All of my Controllers reference this "local" Model. This is a common practice I do. To parse out any "custom components" that are wrapped in {{ }} I have this method on my WinkPost model:

    public function parseCustomTags() {
        $chunks = preg_split("/([{}]{2})/", $this->body, -1, PREG_SPLIT_DELIM_CAPTURE);

        $parsed = '';
        $in_tag = false;
        foreach ($chunks as $chunk) {
            if ($chunk === '{{') {
                $in_tag = true;
                continue;
            }
            else if ($chunk === '}}') {
                $in_tag = false;
                continue;
            }

            if ($in_tag) {
                $tag = json_decode('{' .trim($chunk). '}');
                foreach ($tag as $k=>$v) {
                    if (method_exists($this, 'parse' .studly_case($k))) {
                        $parsed .= call_user_func('App\WinkPost::parse' .studly_case($k), $tag->OGBadge);
                    }
                }
            }else{
                $parsed .= $chunk;
            }
        }

        $this->body = $parsed;

        return $this;
    }

Then, if I place {{ "OGBadge": { "src": "https://completecodesolutions.com/" } }} within the post body, parseCustomTags() will in turn fire the following function and add the return to the post body (replacing the "custom component"):

    public static function parseOGBadge($data) {
        $og_data = OpenGraph::fetch($data->src);

        $title = isset($og_data['title']) ? $og_data['title'] : null;
        $description = isset($og_data['description']) ? $og_data['description'] : null;
        $url = isset($og_data['url']) ? $og_data['url'] : $data->src;
        $image = isset($og_data['image']) ? $og_data['image'] : null;

        return view('blog.partials.ogbadge', compact(
            'title',
            'description',
            'url',
            'image'
        ));
    }

The only other piece is that in my show() method on my BlogController, after retrieving the Post I execute $post->parseCustomTags();.

So that's my proof-of-concept. I'm not sure if you might feel this concept is outside of the scope of the intentions of this package, but I thought I would bring it up in case you are interested. Another option would be to integrate similar functionality into the WYSIWYG kitchen sink/controls. I know that the Wink package is aimed at developers, so I thought "allowing people to type a little JSON into the WYSIWYG maybe isn't such a bad thing" ;)

@themsaid
Copy link
Owner

themsaid commented Jan 7, 2019

Well it isn't aimed for only developers, it's generally for all content creators.

What you showcase here is very interesting indeed, if we can allow custom editor components to be added and configured just like adding an image or custom HTML that would be great.

Might look into this soon :)

@themsaid themsaid added the idea New feature or request label Jan 7, 2019
@mattrabe
Copy link
Author

mattrabe commented Jan 7, 2019

If the target is all content creators then I agree that maybe this could be added to the editor components. Perhaps allow the user to enter a Key and a Value, where in my example above the Key would be "OGBadge" and the Value would be "{ "src": "https://completecodesolutions.com/" }". Allow for flexibility so that the Value might accept a string or a number or JSON, etc. Or, probably better, somehow "register" a custom editor component using a Controller/Model/Trait/something, and then that results in a custom button next to Image & HTML in the editor. Clicking on it reveals some sort of input, potentially also defined by the Controller/Model/Trait. At that point, we're pretty much talking about creating "plugins," which I don't know if you have put much thought into yet.

By the way, though I don't like Wordpress's naming conventions, the equivalent to the wrapped-JSON-in-post-body in Wordpress is called a "shortcode". There's nothing "short" about it, but it is a code. I think I'll refer to my JSON POC above as a "custom code" moving forward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
idea New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants