Forum


Replies: 2   Views: 2644
Issue with calculating _wordmlunits: a non-numeric value encountered
Topic closed:
Please note this is an old forum thread. Information in this post may be out-to-date and/or erroneous.
Every phpdocx version includes new features and improvements. Previously unsupported features may have been added to newer releases, or past issues may have been corrected.
We encourage you to download the current phpdocx version and check the Documentation available.

Posted by j.ypma  · 27-06-2017 - 12:21

Hi there,

I ran into an issue with phpdocx 7 when using: $docx->embedHTML($html);
This html is created by users using an editor and stored into the database.
When merging I sometimes get the error-message below:

in HTML2WordML.inc (line 2563)

at HandleExceptions->handleError(2, 'A non-numeric value encountered', '/Users/jarichypma/projecten/inkoopwegwijzer5/phpdocx/Classes/Phpdocx/Transform/HTML2WordML.inc', 2563, array('sHtmlUnit' => null, 'fontSize' => false, 'match' => array('', '', ''), 'widthType' => 'dxa'))in HTML2WordML.inc (line 2563)

After some digging around I found out that the _wordMLUnits-method in HTML2WordML.inc raises this error. The problem occurs when the parameter $sHtmlUnit has a null-value.

I first tried to fix/sanitize my html, but that leads to nothing. So I wrote a small fix to check for a null-value. If so, return false right away.

    /**
     * Translates HTML units to Word ML units
     *
     * @access private
     * @param string $sHtmlUnit Units in HTML format
     * @param string $fontSize Font size, if applicable
     * @return array
     */
    private function _wordMLUnits($sHtmlUnit, $fontSize = false)
    {
        // Jarich.eu 2017-06-27
        // Check if $sHtmlUnit is not null, if it is null return right away
        if( is_null($sHtmlUnit) ){
            return false;
        }

        if (!preg_match('/^(-?\d*\.?\d*)(%|em|pt|px)?$/i', trim($sHtmlUnit), $match))
            return(array(0, 'dxa'));
        
        $match[1] = (strpos($match[1], '.') === 0 ? '0' : '') . $match[1];
        $match[2] = empty($match[2]) ? '' : $match[2];

        //if($match[2] != 'em' && $match[2] != 'px' && !empty($fontSize)) $match[2] = 'pt';

        switch ($match[2]) {
            case '%': //in WordML the precentage is given in fiftieths of a percent
                $widthType = 'pct';
                $width = 50 * $match[1];
                break;
            case 'em':
                $widthType = 'dxa';
                $width = 20 * $match[1] * $fontSize;
                break;
            case 'pt': //in WordML the width is given in twentieths of a point
                $widthType = 'dxa';
                $width = 20 * $match[1];
                break;
            case 'px': //a pixel is around 3/4 of a point
            default: //if no unit we asume is given in pixels
                $widthType = 'dxa';
                $width = 15 * $match[1];
        }

        return(array($width, $widthType));
    }

Is my approach the right one? And if so, can this fix be added to the codebase?

Regards,

Jarich

Posted by admin  · 27-06-2017 - 13:34

Hello,

We move your patch to the dev team to be checked. We'll update this same topic.

Regards.

Posted by admin  · 06-07-2017 - 11:39

Hello,

The dev team has checked your change. Although a null unit should happen, the best solution is returning a valid width and type if null:

// check if the unit is not set
if ($sHtmlUnit == null) {
    return(array(0, 'dxa'));
}

This is the whole method with the change applied:

    private function _wordMLUnits($sHtmlUnit, $fontSize = false)
    {
        // check if the unit is not set
        if ($sHtmlUnit == null) {
            return(array(0, 'dxa'));
        }

        if (!preg_match('/^(-?\d*\.?\d*)(%|em|pt|px)?$/i', trim($sHtmlUnit), $match)) {
            return(array(0, 'dxa'));
        }

        $match[1] = (strpos($match[1], '.') === 0 ? '0' : '') . $match[1];
        $match[2] = empty($match[2]) ? '' : $match[2];

        //if($match[2] != 'em' && $match[2] != 'px' && !empty($fontSize)) $match[2] = 'pt';

        switch ($match[2]) {
            case '%': //in WordML the precentage is given in fiftieths of a percent
                $widthType = 'pct';
                $width = 50 * $match[1];
                break;
            case 'em':
                $widthType = 'dxa';
                $width = 20 * $match[1] * $fontSize;
                break;
            case 'pt': //in WordML the width is given in twentieths of a point
                $widthType = 'dxa';
                $width = 20 * $match[1];
                break;
            case 'px': //a pixel is around 3/4 of a point
            default: //if no unit we asume is given in pixels
                $widthType = 'dxa';
                $width = 15 * $match[1];
        }

        return(array($width, $widthType));
    }

This change will be added in the next version of phpdocx.

Regards.