askupasoftware/wp-dynamic-css

Is it possible to output a css variable that is stored in an array?

Closed this issue · 16 comments

Is it possible to output css variables that are stored in an array? like Google Fonts below?

[Heading_Text-H1-Font-Value] => Array
  (
    [family]  => Open Sans
    [variant] => regular
    [font]    => google
  )

That's a good point. Enabling array keys can be useful. Currently it is not supported, but it can be if we tweak the regex a little bit. For example #\$([\w]+)(?:\['([\w]+)'\])?# returns 2 matches - one for the variable name, and one for the key.

However that means that we need to change the compiler function as well:

protected function compile_css( $css, $callback )
{   
    return preg_replace_callback( '#\$([\w]+)(?:\['([\w]+)'\])?#', function( $matches ) use ( $callback ) {
        return call_user_func_array( $callback, array($matches[1],$matches[2]) );
    }, $css);
}

And then we set our callback like so:

function my_dynamic_css_callback( $var_name, $arr_key )
{
    $font = get_theme_mod($var_name);
    return $font[$arr_key]
}
wp_dynamic_css_set_callback( 'my_dynamic_style', 'my_dynamic_css_callback' );

I haven't tested it yet though, but you are welcome to try.
By the way http://www.regexr.com/ is a great tool for testing regexes.

Ok, sounds good but I'm a little lost.

Thanks for the site link. I actually bookmarked and used that one yeterday when I was looking for the plus sign question I made yesterday. I try testing out or achieving it myself before asking for help. Glad you shared though, because that was without a doubt the best Regex site I could find.

I'm new at regex, except this I created and know how to tweak..

$developer_mode_custom_theme_skin = preg_replace('/\b.min\b/', '', $custom_theme_skin);

which removes the .min so the normal formatted file will load in my developer mode setting.

Regarding the array_keys testing...

The regex throws Parse error: ... unexpected ')'... 170

Second, I'm not sure how write thereturn $font[$arr_key] in the css.

Should it look like...?

h1 {
    font-family: '$h1[family]', sans-serif;
}

I wouldn't think it should look like...

h1 {
    font-family: '$family', sans-serif;
}

because that would run into other [family] issues, like for h2, h3 or p, etc.

Sorry, I meant css more like what you wrote, to be specific...

$h1 = get_theme_mod($var_name);
return $h1[$arr_key]
$h2 = get_theme_mod($var_name);
return $h2[$arr_key]

Then css...


h1 {
    font-family: '$h1[family]', sans-serif;
}
h1 {
    font-family: '$h2[family]', sans-serif;
}

Or...

$h1_family = get_theme_mod($var_name);
return $h1_family[$arr_key]
$h2_family = get_theme_mod($var_name);
return $h2_family[$arr_key]

Then css...


h1 {
    font-family: '$h1_family', sans-serif;
}
h1 {
    font-family: '$h2_family', sans-serif;
}

In your dynamic CSS file you would be using it like so:

h1 {
    font: $font['size'] $font['weight'] $font['family'];
}

Thanks for the update. Sounds fair enough.

Could you help with the regex error? Ive tried at it, but have gotten know where. I'm assuming that the ")" just needs to have some prefix so it is not "unexpected" in the output.

Which causes the regex throws Parse error: ... unexpected ')'... on line xxx

Can you post the full error message including file names and line numbers?

Sure.

The Error:
Parse error: syntax error, unexpected ')' in /Users/noahjchampion/Projects/-Dev/customtheme.baby/wp-content/themes/custom-theme/assets/dynamic-css/compiler.php on line 170

My line 170 is the regex line which is your Line #177

The unexpected ) I did narrow down to the ) after the 2nd + sign (I believe).
Reference: #\$([\w]+)(?:\['([\w]+)'\])?#

That's because I was using single quotes inside the regex, which caused the string to terminate early. Try changing it to double quotes like so:

protected function compile_css( $css, $callback )
{   
    return preg_replace_callback( "#\\$([\\w]+)(?:\\['([\\w]+)'\\])?#", function( $matches ) use ( $callback ) {
        return call_user_func_array( $callback, array($matches[1],@$matches[2]) );
    }, $css);
}

Note that I had to escape all the backslashes inside the regex since we are using double quotes. Also, I'm using @ to suppress PHP notice messages in case there is no array key.

Ok.

Maybe we are a little closer?

My array value prints...

[font] => Array
        (
            [family] => Arial
            [variant] => regular
        )

I have css input...

h1 {
    font-family: $font['family'];
    color: $font_color;
}

I get this output...

h1 {
    font-family:; /* This outputs empty */
    color: #; /* This is missing the color value digits with the new function. The previous function prints #dd3333. I have to run both functions, old and new to get the full color output. */
}

Function Reference:

function my_dynamic_css_callback( $var_name, $arr_key )
{
    $font = get_theme_mod($var_name);
    return $font[$arr_key];
}
wp_dynamic_css_set_callback( 'my_dynamic_style', 'my_dynamic_css_callback' );

You need to check what get_theme_mod($var_name) is returning.
Try var_dump(get_theme_mod($var_name)). Perhaps it is not returning an array. Also check what the value of $arr_key is.

I updated this thread last night but must have did it wrong.

I was able to get the stored array values to output correctly with the $arr_key, but it conflicts with the normal $var_name

Like...

h1 { font-family: '$font['family']'; }

Returns... (for example)

h1 { font-family: 'Opens Sans'; }

But running the new $arr_key function causes digits in the css of other variables to return empty.

Example...

h1 { color: $font_color; }

Returns...

h1 { color: #; /* no color value, just the hashtag */ }

I tested running both functions for separate enqueues to see that both work correctly for their purpose, but not together.

I'm not sure how or if return $font[$arr_key]; and return $get_theme_mod($var_name); can run in the same function?

Here's is what I have below in a snapshot look...

// ---------------------------------------------------------------------------------------------------
// @TEST
//   enqueue wp dynamic css function...
// ---------------------------------------------------------------------------------------------------
add_action('wp_enqueue_scripts', 'test_this');
function test_this() {
    wp_dynamic_css_enqueue('test-styles', CUSTOM_THEME_BACKEND_PATH . CustomTheme_Constants::ASSETS_CORE_CSS . '/test-styles.css');
    wp_dynamic_css_enqueue('test-font', CUSTOM_THEME_BACKEND_PATH . CustomTheme_Constants::ASSETS_CORE_CSS . '/test-font.css');
}
// ---------------------------------------------------------------------------------------------------
// @TEST
//   $var_name function...
//   h1 { color: $font_color; } outputs proper color values like "#dd3333"
// ---------------------------------------------------------------------------------------------------
wp_dynamic_css_set_callback('test-styles', 'my_dynamic_css_callback1');
function my_dynamic_css_callback1($var_name) {
    return get_theme_mod($var_name);
}
// ---------------------------------------------------------------------------------------------------
// @TEST
//   $arr_key function...
//   h1 { font-family: $font['family']; } outputs empty color values like "#"
// ---------------------------------------------------------------------------------------------------
wp_dynamic_css_set_callback('test-font', 'my_dynamic_css_callback2');
function my_dynamic_css_callback2($var_name, $arr_key) {
    $font = get_theme_mod($var_name);
    return $font[$arr_key];
}

This HTML source screenshot might give a better visual...

view-source customtheme baby-12-04-2016-cgtft

Is this a problem with combining the two returns into one or something else or am I doing something wrong?

I will have to look into it and test it locally to see exactly how this can be implemented properly.
Also, I saw your review on WordPress.org and wanted to say thanks!
Just as a side note regarding your comment - the purpose of this library is to allow you to create stylesheets from dynamic user data. It is not, however, intended to be used in place of a CSS preprocessor such as SASS or LESS. Those serve a completely different purpose. There are huge benefits in using CSS preprocessors, and I do recommend you to learn these languages (well, only one of them).
I, for example, use SASS to precompile the majority of my CSS, and then use this library to generate only the CSS rules that are based on user input. The result is having 2 CSS files: one large static CSS file (minified), and a smaller dynamic CSS file. Hope that makes sense.

@ykadosh

Ok, thanks. Yeah, I've tried about 4 or 7 methods of combing the return values, but nothing worked. I always got the same conflict.

Thanks about the CSS Processors. I'm using WP Dynamic Css as intended then. I'm only using it to generated user's chosen dynamic styles and so I can still learn SCSS a little later to replace my standard stylesheet method.

@ykadosh

Any chance to check this out yet or know when you might?
-- Not trying to rush as it is your project and work at your own time, but if you can offer a time when you expect to be able to look into it, I'd appreciate it and can also test it to confirm.

Thanks!

Hi Noah,
You'll be happy to hear that I have added support for array subscripts (v1.0.3). I've also updated the documentation accordingly. Please take a look at the "Setting the Value Callback Function" section to see how to use the new feature.
Please test and let me know if you have any issues or questions. Thank you for your support!

@ykadosh

Appreciate it.

I've tested it out and it works solid.

Welcome and thanks again!