Using wp_filesystem in Plugins to store customizer settings

I try to fix my plugin with the answers i got here: Using wp_filesystem in Plugins
Background i wrote a theme (https://github.com/bassjobsen/jamedo-bootstrap-start-theme) and a plugin (https://github.com/bassjobsen/wp-less-to-css) now i want to integrate the plugin in the theme. The plugin wrote a CSS file to a folder. Write files with native PHP function is not secure as described here: http://ottopress.com/2011/tutorial-using-the-wp_filesystem/. The previous answer helps me to fix this issues for the plugin.

The solution provide by @otto relays on request_filesystem_credentials which seems to requires a URL. This URL will give me some troubles when integrate the plugin with the theme.

Read More

My target is to use settings from the customizer after saving to create a new css file.

Now i have in functions.php:

add_action( 'customize_save_after', 'lesscustomize' );

function lesscustomize($setting)
{
//$setting is no used here
$updatecss = WP_LESS_to_CSS::$instance;
add_filter( 'add_extra_less_code', 'add_extra_less_now_live');

function add_extra_less_now_live($parser)
{
    return 'h1{color:'.get_theme_mod( 'heading_color').'}';          
}
$updatecss->wpless2csssavecss();
}

Where wpless2csssavecss() now saves the file with file_put_contents.
The file_put_contents should be replace with a $wp_filesystem->put_contents();. Cause $wp_filesystem will be used as a global i think it should be possible to get the file system credentials in my lesscustomize() function. Beside i have no idea how to do this without a URL. There will be a URL but it is called by Ajax and not visible for the user.

The idea to use ‘customize_save_after’ came from https://stackoverflow.com/questions/14802251/hook-into-the-wordpress-theme-customizer-save-action/16679837

My initial question will it be possible to get file system credentials in my lesscustomize()?
Or if not will there be an alternative to hook the customizer settings save action and get file system credentials to save my settings?

update
In this update of the question, i will react on the useful answer of
Mark Kaplun. I expect this will help to understand my initial question.

What you are trying to do is wrong if it is for general purpose use and is not >tailored for the needs of a specific client. Dynamically modifying your >theme’s code, and css is code like JS, is usually a bad idea that bring only >maintenance problems

In my theme i use LESS in stead of CSS (although you could also write CSS). I think this will be useful and fits the needs of the theme users. In the first place LESS keeps things clean and in the second place my theme is build with Twitter’s Bootstrap. LESS will be the most kind of direct way to modify Bootstrap based HTML/CSS.
I don’t modify my theme code, i only want to save my CSS to file, where CSS will be compiled from LESS. Maintenance strategy of the code i have described here: http://bassjobsen.weblogs.fm/integrate-less-jbst-wordpress-theme/

In addition to the theoretical reasons there are user expectations
related to the UX of theme customization which do not involve writing
files to the server.

I do not understand what write files has to do with UX. People using my theme choose a theme which use Bootstrap and so LESS. I think they should understand there should be written files somewhere.
I agree an extra step for filling in your credentials will give a bad UX.

If you truly need to save files on the server then the right place for them is >the /wp-content/uploads directory.

Yes, that’s what i do now. http://ottopress.com/2011/tutorial-using-the-wp_filesystem/ tells me it is a bad idea. Since WP3.8 it will also don’t pass the theme tests on wordpress.org: “WARNING: file_put_contents was found in the file wp-less-to-css.php possible file operations.”

The better way to do it is to have minimal LESS files that are
relevant only to the options that are controlled by the user. once the
options are changed you compile the LESS and store the generated CSS
in an option and output it as part of each pages HTML, like most
themes are doing with their customizable options.

I agree this could be an option. Writing inline CSS does not be the best solution always, see also: https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery. Not all customization setting have to be critical or part of the above-the-fold CSS. Beside in my case some setting will also recompile Bootstrap’s CSS (for example changing the @grid-float-breakingpoint) i can not inline thhis code.

Related posts

2 comments

  1. What you are trying to do is wrong if it is for general purpose use and is not tailored for the needs of a specific client. Dynamically modifying your theme’s code, and css is code like JS, is usually a bad idea that bring only maintenance problems – are you validating all values to be able to compile? How will you handle upgrades? How will you handle network installs where users don’t know the FTP credentials?

    In addition to the theoretical reasons there are user expectations related to the UX of theme customization which do not involve writing files to the server.

    If you truly need to save files on the server then the right place for them is the /wp-content/uploads directory.

    The better way to do it is to have minimal LESS files that are relevant only to the options that are controlled by the user. once the options are changed you compile the LESS and store the generated CSS in an option and output it as part of each pages HTML, like most themes are doing with their customizable options.

  2. update

    The session option describe below seems very insecure! Further investigation make clear the array returned by request_filesystem_credentials contains your credentials in plain text. So store this in a session seems a bad idea.

    Note sending the credentials over an non-secure connection (http) when posting the form also seems a bad idea. The latest can be solved by adding your credentials to wp_config.php. When doing this make sure to chmod 600 your wp_config.php (see: http://codex.wordpress.org/Changing_File_Permissions).

    Setting the credentials in wp-config.php for example:

    define('FS_METHOD', 'ftpext');
    define('FTP_HOST', 'localhost');
    define('FTP_USER', 'ftpuser');
    define('FTP_PASS', 'ftpuser');
    define('FTP_BASE', '/home/username/http_docs/');
    

    After doing this we can save them ( temporary ) to the database for use by the customizer. This seems save to do cause the setting from wp-config.php are saved to the database too. Saving to the database will be done with set_theme_mod inspired by: https://stackoverflow.com/questions/14802251/hook-into-the-wordpress-theme-customizer-save-action/16679837

    After doing all this the final code which enable me to store the customizer setting in a file using wp_filesystem:

    function lesscustomize($setting)
    {
    $updatecss = WP_LESS_to_CSS::$instance;
    $updatecss->wpless2csssavecss(unserialize(get_theme_mod('customizercredits')));
    }
    
    add_action( 'customize_save_after', 'lesscustomize' );
    
    function storecedits( $wp_customize ) {
    
                $in = true;
                $url = 'customize.php';
                if (false === ($creds = request_filesystem_credentials($url, '', false, false,null) ) ) {
                    $in = false;
                    exit;
                }
    
                if ($in && ! WP_Filesystem($creds) ) {
                    // our credentials were no good, ask the user for them again
                    request_filesystem_credentials($url, '', true, false,null);
                    $in = false;
                    exit;
                }
    
                set_theme_mod('customizercredits', serialize($creds));
    
    }
    add_action('customize_controls_init', 'storecedits', 1);  
    

    —————– end update ———————-

    I found i can solve the problem theoretical by using sessions. Unfortunately this introduce new questions about security. First will enable sessions (found here https://stackoverflow.com/a/4769449/1596547) cause any other trouble? and if not what are the risks of storing my file credentials in a session?

    function kana_init_session()
    {
      session_start();
    }
    
    add_action('init', 'kana_init_session', 1);
    
    function updatefiles( $wp_customize ) {
    WP_Filesystem($_SESSION['creds']);
    
                global $wp_filesystem;
                $contentdir = trailingslashit( $wp_filesystem->wp_content_dir() ); 
                echo $contentdir;
                $wp_filesystem->mkdir( $contentdir. 'cbe' );
                if ( ! $wp_filesystem->put_contents(  $contentdir . 'cbe/test.txt', 'Test file contents', FS_CHMOD_FILE) ) 
                {
                    echo "error saving file!";
                }
    
    
    
    }
    
    add_action('customize_save', 'updatefiles', 1);
    
    function storecredentials( $wp_customize ) 
    {
    
                $in = true;
                $url = 'customize.php';
                if (false === ($creds = request_filesystem_credentials($url, '', false, false,null) ) ) {
                    $in = false;
                    exit;
                }
                if ($in && ! WP_Filesystem($creds) ) {
                    // our credentials were no good, ask the user for them again
                    request_filesystem_credentials($url, '', true, false,null);
                    $in = false;
                    exit;
                }
                $_SESSION['creds'] = $creds;
    
    }
    add_action('customize_controls_init', 'storecredentials', 1);</strike>
    

Comments are closed.