Support » Plugin: The Events Calendar: Category Colors » Writing to CSS file failing

  • Resolved dpegasusm

    (@dpegasusm)


    We are seeing a lot of errors like:

    PHP Warning: file_put_contents(/wp-content/uploads/teccc_*.css): failed to open stream: No such file or directory in /wp-content/plugins/the-events-calendar-category-colors/src/Category_Colors/Frontend.php on line 144

    Due to the fact that the plugin is trying to write to a cache file on a load balanced environment so they key specified is not always valid because the file does not necessarily exist on that server but another server behind the load balancer. Is there a way to override this behavior and have it write to a file in a predefined location without the key or bypass this behavior entirely and serve from a CDN?

Viewing 15 replies - 1 through 15 (of 18 total)
  • Plugin Author Andy Fragen

    (@afragen)

    That’s an interesting problem. The file is writing to a constant location, /wp-content/uploads/teccc-***{.min}.css.

    Given your load balancer, what do you suggest?

    Thread Starter dpegasusm

    (@dpegasusm)

    Wordpress has the filter wp_get_custom_css

    
    /**
     * Filters the Custom CSS Output into the <head>.
     *
     * @since 4.7.0
     *
     * @param string $css        CSS pulled in from the Custom CSS CPT.
     * @param string $stylesheet The theme stylesheet name.
     */
    $css = apply_filters( 'wp_get_custom_css', $css, $stylesheet );
    

    It might be possible to append the CSS to the WP custom CSS output using that hook or do something similar to how WP is handling the Custom CSS output instead of writing it to a file.

    Thread Starter dpegasusm

    (@dpegasusm)

    Jetpack is also doing some realtime display of their CSS files without writing it to disk:

    https://github.com/Automattic/jetpack/blob/89a9af96b669e2e5a2ed47d3f3e07c804d6e0dd0/modules/custom-css/custom-css.php

    Plugin Author Andy Fragen

    (@afragen)

    @dpegasusm the whole point of this plugin is to produce a CSS file. I intentionally try to load this file very late so that I can override other theme specific CSS.

    My question to you is more, why doesn’t your load balancer _see_ the CSS file? It is created in a standard WordPress path. Is there some other location in wp-content where your load balancer would see the file?

    This is the first time I’ve ever had this issue and I’d like to know more about how you load balancer works in order to provide the best possible fix.

    Does the file exist within your load balancer and what is that path?

    Thread Starter dpegasusm

    (@dpegasusm)

    The load balancer behaves like a round robin connecting to anywhere between 5-20 servers a time depending on load requirements so the CSS file exists on one server which may or may not be the server an end user ends up connecting to. On the read/write end the file could be written to one server but not to others so the file that is being looked for may not be found. For example:

    On server one the files are called:
    teccc_aa580578f69ec3d2c0062de7c652ca2d.css
    teccc_aa580578f69ec3d2c0062de7c652ca2d.min.css

    On server two we have:
    teccc_f0fd8b4e32c410052774ee38ca793538.css
    teccc_f0fd8b4e32c410052774ee38ca793538.min.css

    On server 3 we have:
    teccc_0829174adf7de37a6fc47e92231b13c1.css
    teccc_0829174adf7de37a6fc47e92231b13c1.min.css

    Additionally, every time a server is destroyed the files are destroyed with that server and since they are only created by the plugin locally on that one instance and not pushed to a CDN the cease to exist completely.

    So the load balancer doesn’t __see__ it because it is not intelligently looking for it and just doing a dumb passthrough. If the user happens to be the 1/5 chance of connecting to the server with the correctly named file then they get the styles otherwise no, but once that server is taken out of commission due to the autoscaling with load the files cease to exist as well.

    • This reply was modified 3 years, 3 months ago by dpegasusm.
    Plugin Author Andy Fragen

    (@afragen)

    So the hash should only really change when the plugin options change. Additionally it is stored for 28 days before it would be regenerated. The hash is created here, https://github.com/afragen/the-events-calendar-category-colors/blob/develop/src/Category_Colors/Frontend.php

    It seems that the load balancer must have some canonical source. I could add a filter into that function so you can set the hash, but I’m not certain how that would affect browser caching, etc.

    Do you think that might work?

    Thread Starter dpegasusm

    (@dpegasusm)

    On closer look, I think that the root of the issue is that the plugin assumes that the file its trying to write to on 144/145 exists:

    https://github.com/afragen/the-events-calendar-category-colors/blob/develop/src/Category_Colors/Frontend.php#L144

    If a check was added to determine if the file exists and if not create it before writing that may solve the issue too.

    In our setup we have a cache in front of the load balancer on all CSS files that we can manually invalidate objects in but standard browser caching rules still apply. If there was a way to permanently set the hash via filter as you described or append the hash to the file via query string parameter like filename.css?ver=hash instead of in the file name then that might solve both the browser cache issue and the file writing issue.

    Plugin Author Andy Fragen

    (@afragen)

    https://www.php.net/manual/en/function.file-put-contents.php

    > If filename does not exist, the file is created. Otherwise, the existing file is overwritten, unless the FILE_APPEND flag is set.

    https://github.com/afragen/the-events-calendar-category-colors/commit/71838714e13b6e46eca1e90f567eeed24244e684

    Try this branch and let me know how how it works.

    https://github.com/afragen/the-events-calendar-category-colors/archive/develop.zip

    The following example should show you how to use the filter.

    
    add_filter('teccc_set_options_hash', function () {
    	return 'my-static-hash';
    });
    
    • This reply was modified 3 years, 3 months ago by Andy Fragen.
    Thread Starter dpegasusm

    (@dpegasusm)

    So this is actually looking like a two part issue. First part we mentioned above, but the second part is the files and images are offloaded to a CDN. This means that the entire uploads folder doesn’t exist on the server so when it is trying to write to it with file_put_contents the tree doesn’t exist and the pathway fails.

    A few things could fix this:

    can wp_upload_dir(); be used on line #33 instead of wp_get_upload_dir(); so that the directory is created if it fails to exist.

    Alternately could the writing of the file be handled by the WP_Filesystem API? This would make it easy for us to put the file into our CDN and bypass the LB/hash issue entirely.

    • This reply was modified 3 years, 3 months ago by dpegasusm.
    • This reply was modified 3 years, 3 months ago by dpegasusm.
    • This reply was modified 3 years, 3 months ago by dpegasusm.
    Plugin Author Andy Fragen

    (@afragen)

    Have you tried seeing if wp_upload_dir() fixes the issue?

    Does this mean that the above filter for the hash isn’t needed?

    Thread Starter dpegasusm

    (@dpegasusm)

    We still need the above filter to modify the hash. It also needs to check for and create the directory (or directory path) before trying to write to it.

    Plugin Author Andy Fragen

    (@afragen)

    @dpegasusm the above filter does replace the hash with a value of your choosing. You will need to add the ?refresh_css query arg to the event URL to update the CSS.

    Did you try changing the code to see if wp_upload_dir() solves the issue of creating the directory for you?

    Thread Starter dpegasusm

    (@dpegasusm)

    Thank you. Yes that filter is exactly what we need for one part of the puzzle.

    I have tested and changing the code to use wp_upload_dir() creates the directory and files without error as needed.

    Plugin Author Andy Fragen

    (@afragen)

    Thanks for the confirmation. I will have an update for this soon.

    Plugin Author Andy Fragen

    (@afragen)

    @dpegasusm updates are in develop branch. Can you download from the link and make sure this solves your problem? Thanks.

    https://github.com/afragen/the-events-calendar-category-colors/archive/develop.zip

Viewing 15 replies - 1 through 15 (of 18 total)
  • The topic ‘Writing to CSS file failing’ is closed to new replies.