0
\$\begingroup\$

I'm working on a site running woocommerce and wp where the user will add/has added a dimension attribute.

The dimension string will take the following format originally:

Ht: 30 1⁄2" W: 22 1⁄2" D: 18"

and should return the string with html to format the fraction e.g:

Ht: 30 <sup>1</sup>&frasl;<sub>2</sub>" W: 22 <sup>1</sup>&frasl;<sub>2</sub>" D: 18"

will the following to consider:

  • The amount of fractions in the string will be unknown (0 - X)
  • The string can be any valid fraction
  • The user may/may not add a space in between the fraction and the quotation e.g Ht: 30 1/2 " W...

Here's my solution:

add_filter( 'woocommerce_attribute', __NAMESPACE__ . '\\format_dimension_attr', 10, 2 );


/**
 * Format fractions in the Dimension attr string to include proper html
 *
 * e.g The 1/2 in 'Height: 5 1/2"' should be
 *
 * <sup>1</sup>&frasl;<sub>2</sub>
 */
function format_dimension_attr( $value, $att ) {

    if ( 'Dimensions' === $att['name'] ) {
        // Use the raw value instead of $value (which includes html)
        $raw = $att->get_options()[0];

        if ( strpos( $raw, '/' ) !== false ) {

            $raw = explode( ' ', $raw );

            // Check for accidental space before quotation and remove it
            // e.g 'height: 5 1/2 "' will produce [5, 1/2, "]
            $raw = array_filter( $raw, function( $val ) {
                return '"' !== $val;
            } );

            // Run through the array
            $raw = array_map( function( $val ) {

                // Format the current item if it contains a slash
                if ( strpos( $val, '/' ) !== false ) {
                    // Remove any " before splitting
                    $val = explode( '/', trim( $val, '"' ) );
                    $val = '<sup>' . $val[0] . '</sup>&frasl;<sub>' . $val[1] . '</sub>"';
                }

                return $val;

            }, $raw );

            // Replace the p tag we removed by using the raw value
            $value = wpautop( join( ' ', $raw ) );
        }
    }

    return $value;
}
\$\endgroup\$
1
\$\begingroup\$

Well, regex is often a bad idea, but it's one of the case I find it way better than the alternative :

$raw='30 1/2 et 22 3 / 4';
echo preg_replace('/([0-9]+)\s*\/\s*([0-9]+)/', '<sup>$1</sup>&frasl;<sub>$2</sub>',$raw);

Just test it and see for yourself.

\$\endgroup\$
  • \$\begingroup\$ That's definitely a lot shorter. Can you explain why "Regex is often a bad idea"? \$\endgroup\$ – mrmadhat Sep 3 '18 at 15:02
  • \$\begingroup\$ Regex are so poweful that there is some temptations to use it for about anything like this or that. Also, if you lack the motivation to understand how it work, it put some dark spot in your code that you won't be able to modify later. Finally, it can be quite perf consuming if badly used. \$\endgroup\$ – Nomis Sep 3 '18 at 15:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.