How to configure ob_tidyhandler dynamically?
Asked Answered
T

1

7

The PHP tidy extension has a function ob_tidyhandlerDocs that works with PHP output bufferingDocs as a callback, e.g.:

ob_start('ob_tidyhandler');

I know that Tidy has a lot of configuration settingsDocs, however I am hitting a road block to setup default configuration options for that output buffer callback.

Most of Tidy's PHP function refer to a tidy document or object, however with the output buffering that one is not accessible.

There is a configuration setting tidy.default_config, however that is not change-able at runtime, so it is not very dynamic.

Does anybody know if configuring the callback dynamically is possible at all? I remember I wrote a callback my own, collected all output and repaired it with a call to tidy_repair_stringDocs which accepts configuration as an array. But I thought it would be nice to not need to do that and just pass the configuration along for the output buffer.

Thief answered 24/7, 2012 at 10:44 Comment(0)
T
10

I've had a quick look at the code for the tidy extension, and there is a way to change the configuration for the output buffer handler.

That said, it is not a nice way. It is exploiting a feature of the code which obviously may change in future versions.

The function that handles the buffer processing is php_tidy_output_handler and on line 1191 it calls the macro TIDY_SET_DEFAULT_CONFIG.

If tidy.default_config is not set, then the macro does nothing. If it is set then the configuration file is read from disk and the options are parsed.

Since the configuration file is loaded during the parsing of the output buffer, it is possible to modify the configuration file from your PHP script before parsing begins.

This means you have to make tidy.default_config = /file/writable/by/php and dynamically update this file to contain the options you require. (I told you it was not a nice way).


I can immediately see a problem with this. There is a potential race condition.

If two scripts require different options, and both are executed at the same time, there is the potential for one of the scripts to receive the wrong configuration.

The file is obviously not designed to be changed ad-hocly - and as you can probably follow from the extension code, there is no other available path to inject configuration options, since the options are specific to the document.

  • A new TidyDoc is created.
  • Couple of config flags set + default_config loaded.
  • Buffer is parsed.

Sorry, it feels like in the end I am just delivering bad news.

Your best solution may be to go with a custom ob_start callback where you have full control over the document options.

Edit:

Had a bit of a brainstorm and tried a few things to get around this. Everything has been met with failure.

I tried registering a custom stream wrapper to return per-script values, and set tidy.default_config = tidy://config. It turns out that stream wrappers are not resolved by the config loader and this does not work.

One thing I have not been able to test correctly is the per-directory configuration .user.ini or the [PATH=] ini section. These are both only available with the CGI/FastCGI SAPI (not FPM). I suspect this probably doesn't help you either.

Tabanid answered 2/8, 2012 at 10:27 Comment(2)
Well, delivering bad news it's not so. From the documentation I already expected it does not work, so I asked as well to get a second opinion which you did to a great extend. Thanks a lot for taking the time to look into this. It is probably worth to think about asking for a new setting / context / way to options to that callback as a feature request so this can be better controlled at runtime.Thief
X-Ref: github.com/leight/php-src/commit/…Thief

© 2022 - 2024 — McMap. All rights reserved.