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

Question: Best way to handle a [raw][/raw] shortcode? #31

Closed
rhukster opened this issue Jan 26, 2016 · 11 comments
Closed

Question: Best way to handle a [raw][/raw] shortcode? #31

rhukster opened this issue Jan 26, 2016 · 11 comments
Assignees
Labels

Comments

@rhukster
Copy link

I'm trying to find the best way to write a [raw][/raw] shortcode that stops the Shortcode library from processing anything between these raw tags. My current implementation fakes it by taking setting the 'text' back to the original unmodified text. However, this doesn't stop Shortcode from processing that inner stuff first.

    private function addRawHandler()
    {
        $this->handlers->add('raw', function(ShortcodeInterface $shortcode) {
            $raw = trim(preg_replace('/\[raw\](.*?)\[\/raw\]/is','${1}', $shortcode->getShortcodeText()));
            return $raw;
        });
    }

This raised it's head when I ran into the [0] bug in some javascript example code on my page. While a fix was quickly found, a situation could come up where a fix is impossible or not practical. Turning off shortcodes processing in parts of a page is therefore an important function to have. What is the better way of doing this?

Cheers!

@thunderer thunderer self-assigned this Jan 26, 2016
@thunderer
Copy link
Owner

Use ProcessedShortcode::getTextContent(), it contains the unprocessed content of current shortcode even if auto processing is enabled. I should put some PHPDocs there. :)

@rhukster
Copy link
Author

So it should be this:

    private function addRawHandler()
    {
        $this->handlers->add('raw', function(ProcessedShortcode $shortcode) {
            return trim($shortcode->getTextContent());
        });
    }

??? That inner stuff is not processed at all?

@thunderer
Copy link
Owner

There are several possible solutions:

  • you can recursively check in every handler that none of the parents are raw and if there is any with that name, return ProcessedShortcode::getShortcodeText() immediately. I can add a ProcessedShortcode::hasParentsWithName($name) helper method to make it easier to use,
  • if you turn off auto processing of content and disable recursion then you'll be able to manually handle everything, which means that if you return unprocessed content it will stay as such. This is quite problematic because then you'll need to manually process all shortcode contents by explicitly calling $s->getProcessor()->process($s->getContent()) in every handler,
  • if I finish the event subsystem, you'll be able to register handler for FilterShortcodesEvent and check if current set of shortcodes are processed within parent raw (this connects a little to the first point) and remove all of them if it is true.

I really hope to get that events subsystem done in the near future as it's definitely the way to go here. You may of course ask "why don't you just have Processor::withRawShortcodeNames()?" but in my opinion the library code should make no assumptions about the way programmer wants to process shortcodes, just provide the tools that make everything possible.

@rhukster
Copy link
Author

Hmm, I appreciate your thoughts and solutions, but I don't agree.

I really think that having a method in the library to specifically not process shortcodes is a better solution IMHO. It's like a shortcode needs to be there per say, but a method making it simple for users of the lbrary to create a shortcode such as [raw] seems like a feature that any shortcode library should have.

All your solutions really feel like workarounds that complicate things and really this is something that every shortcode library should be able to do without much work.

@thunderer
Copy link
Owner

I also appreciate the whole discussion we have over all the reported issues. Let me just speak my mind below, I need some time to think about all possible ways of solving that.

My position on this topic is that not processing shortcode is just one of the ways of processing them, that's why you won't find anything directly related to implementing usual [b], [u], [url] shortcodes in the library code (but there is a branch builtin-handlers with which I hope to fill that gap in the proper way). The problem with such simple solutions like withRawShortcodeNames() is that it requires me to put an if() directly inside Processor which really don't belong there. Also, what happens if you want to have [raw] but at the same time you want to enable only subset of handlers inside? This would require another if() and so on. This is why events subsystem is the solution because not only it does what you want, it also does not prevent other possibilities.

BTW I'm sorry, I didn't see the code you posted above - yes, getTextContent() returns unprocessed content regardless of all other configuration options. That content may have been processed (and the result is accessible using getContent()), that's why there are two methods.

@rhukster
Copy link
Author

Yes, I tested it and it does continue to process the shortcodes in between the [raw][/raw] tags, it just ignores it. So it does what it was doing, just a little cleaner. But it's not a proper solution.

I don't think you should include any default shortcodes in the library, and that goes also for [raw][/raw]. I just think you should make the ability to do this in a simple fashion. I can see your point about putting if statements in your processor, but frankly I'm just asking for a simple method to programmatically not process a chunk of the page. Not a shortcode, not every possible combination, but a simple method so that a raw shortcode can be created.

I just feel this is something that would make the library more useful and simpler to use, and isn't that the point of a library such as this in the first place? :)

I just know from real-world experience there will definitely be situations where the parsers are going to choke, and probably on stuff that is not related to shortcodes at all (for example this JS code that triggered this whole thing). I just feel there needs to be some mechanism in place to skip problematic content, and it needs to be something that doesn't require a huge amount of jumping through hoops.

Your library is really nice, but without this, it's going to be very risky to actually use it in a CMS where you can't say for certain that every bit of content is going to be shortcode-safe. Having a mechanism to disable processing for a bit of troublesome content is a solution everyone is familiar with:

eg: https://css-tricks.com/snippets/wordpress/disable-automatic-formatting-using-a-shortcode/

@thunderer
Copy link
Owner

@rhukster I just merged the events subsystem PR #32. You asked about the example how to use those events, I think the test for [raw] shortcode explains it quite well. You need to create an EventContainer, register any callable just like you register handlers for shortcodes and put the container into Processor, that's all. Remember that each event uses its own class, fortunately PHP will complain immediately once it reaches that callable. I prepared two ready to use event listeners as shown in that code. Please tell me what you think. Does this answer your question about the best way to handle [raw] shortcode?

In the meantime I worked on the better documentation in README, it's available in a Gist. Could you please read it and give me some insights - whether it is understandable, maybe some parts should be expanded, maybe something needs better explanation, and so on?

BTW Before tagging v0.6.0 I'd also like to discuss the builtin handlers in #33. I'd appreciate any comments on those PRs, especially ideas for more or less generic handlers that seem useful for you. Thanks for all the motivation I got from discussing those issues!

@thunderer
Copy link
Owner

@rhukster Have you had the chance to review those changes? BTW If those changes solved your problem, can you say so in comments, close this issue and open new one for new discussions?

@rhukster
Copy link
Author

rhukster commented Feb 2, 2016

Ah sorry, not had chance to review/test the events handler yet. i have been refactoring some other area of Grav over the weekend that i discovered had some bugs (after writing some in depth unit tests!).

I should finish up my other work this morning, and ill test the events this afternoon. Thanks!

@rhukster
Copy link
Author

rhukster commented Feb 3, 2016

Ok, had chance to test this, and yes it does work fine now! My raw handler function looks like this:

    private function addRawHandler()
    {
        $this->handlers->add('raw', function(ShortcodeInterface $shortcode) {
            return trim($shortcode->getContent());
        });

        $this->events->addListener(Events::FILTER_SHORTCODES, new FilterRawEventHandler(array('raw')));
    }

So pretty clean and works great! Thanks.

@rhukster rhukster closed this as completed Feb 3, 2016
@thunderer
Copy link
Owner

I'm happy to hear this, thanks! Could you please also look at the open PRs for better documentation #34 and builtin handlers in #33? Any suggestions would be greatly appreciated.

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

No branches or pull requests

2 participants