Exemple #1
0
 /**
  * Analyse the CSS properties from the HTML parsing
  *
  * @param string $tagName
  * @param array  $param
  * @param array  $legacy
  *
  * @return boolean
  */
 public function analyse($tagName, &$param, $legacy = null)
 {
     // prepare the informations
     $tagName = strtolower($tagName);
     $id = isset($param['id']) ? strtolower(trim($param['id'])) : null;
     if (!$id) {
         $id = null;
     }
     $name = isset($param['name']) ? strtolower(trim($param['name'])) : null;
     if (!$name) {
         $name = null;
     }
     // get the class names to use
     $class = array();
     $tmp = isset($param['class']) ? strtolower(trim($param['class'])) : '';
     $tmp = explode(' ', $tmp);
     foreach ($tmp as $k => $v) {
         $v = trim($v);
         if ($v) {
             $class[] = $v;
         }
     }
     // prepare the values, and the list of css tags to identify
     $this->value['id_tag'] = $tagName;
     $this->value['id_name'] = $name;
     $this->value['id_id'] = $id;
     $this->value['id_class'] = $class;
     $this->value['id_lst'] = array();
     $this->value['id_lst'][] = '*';
     $this->value['id_lst'][] = $tagName;
     if (count($class)) {
         foreach ($class as $v) {
             $this->value['id_lst'][] = '*.' . $v;
             $this->value['id_lst'][] = '.' . $v;
             $this->value['id_lst'][] = $tagName . '.' . $v;
         }
     }
     if ($id) {
         $this->value['id_lst'][] = '*#' . $id;
         $this->value['id_lst'][] = '#' . $id;
         $this->value['id_lst'][] = $tagName . '#' . $id;
     }
     // get the css styles from class
     $styles = $this->getFromCSS();
     // merge with the css styles from tag
     $styles = array_merge($styles, $param['style']);
     if (isset($param['allwidth']) && !isset($styles['width'])) {
         $styles['width'] = '100%';
     }
     // reset some styles, depending on the tag name
     $this->resetStyle($tagName);
     // add the legacy values
     if ($legacy) {
         foreach ($legacy as $legacyName => $legacyValue) {
             if (is_array($legacyValue)) {
                 foreach ($legacyValue as $legacy2Name => $legacy2Value) {
                     $this->value[$legacyName][$legacy2Name] = $legacy2Value;
                 }
             } else {
                 $this->value[$legacyName] = $legacyValue;
             }
         }
     }
     // some flags
     $correctWidth = false;
     $noWidth = true;
     // read all the css styles
     foreach ($styles as $nom => $val) {
         switch ($nom) {
             case 'font-family':
                 $val = explode(',', $val);
                 $val = trim($val[0]);
                 if ($val && $val != 'inherit') {
                     $this->value['font-family'] = $val;
                 }
                 break;
             case 'font-weight':
                 $this->value['font-bold'] = $val == 'bold';
                 break;
             case 'font-style':
                 $this->value['font-italic'] = $val == 'italic';
                 break;
             case 'text-decoration':
                 $val = explode(' ', $val);
                 $this->value['font-underline'] = in_array('underline', $val);
                 $this->value['font-overline'] = in_array('overline', $val);
                 $this->value['font-linethrough'] = in_array('line-through', $val);
                 break;
             case 'text-indent':
                 $this->value['text-indent'] = $this->cssConverter->convertToMM($val);
                 break;
             case 'text-transform':
                 if (!in_array($val, array('none', 'capitalize', 'uppercase', 'lowercase'))) {
                     $val = 'none';
                 }
                 $this->value['text-transform'] = $val;
                 break;
             case 'font-size':
                 $val = $this->cssConverter->convertToMM($val, $this->value['font-size']);
                 if ($val) {
                     $this->value['font-size'] = $val;
                 }
                 break;
             case 'color':
                 $res = null;
                 $this->value['color'] = $this->cssConverter->convertToColor($val, $res);
                 if ($tagName == 'hr') {
                     $this->value['border']['l']['color'] = $this->value['color'];
                     $this->value['border']['t']['color'] = $this->value['color'];
                     $this->value['border']['r']['color'] = $this->value['color'];
                     $this->value['border']['b']['color'] = $this->value['color'];
                 }
                 break;
             case 'text-align':
                 $val = strtolower($val);
                 if (!in_array($val, array('left', 'right', 'center', 'justify', 'li_right'))) {
                     $val = 'left';
                 }
                 $this->value['text-align'] = $val;
                 break;
             case 'vertical-align':
                 $this->value['vertical-align'] = $val;
                 break;
             case 'width':
                 $this->value['width'] = $this->cssConverter->convertToMM($val, $this->getLastWidth());
                 if ($this->value['width'] && substr($val, -1) == '%') {
                     $correctWidth = true;
                 }
                 $noWidth = false;
                 break;
             case 'height':
                 $this->value['height'] = $this->cssConverter->convertToMM($val, $this->getLastHeight());
                 break;
             case 'line-height':
                 if (preg_match('/^[0-9\\.]+$/isU', $val)) {
                     $val = floor($val * 100) . '%';
                 }
                 $this->value['line-height'] = $val;
                 break;
             case 'rotate':
                 if (!in_array($val, array(0, -90, 90, 180, 270, -180, -270))) {
                     $val = null;
                 }
                 if ($val < 0) {
                     $val += 360;
                 }
                 $this->value['rotate'] = $val;
                 break;
             case 'overflow':
                 if (!in_array($val, array('visible', 'hidden'))) {
                     $val = 'visible';
                 }
                 $this->value['overflow'] = $val;
                 break;
             case 'padding':
                 $val = explode(' ', $val);
                 foreach ($val as $k => $v) {
                     $v = trim($v);
                     if ($v != '') {
                         $val[$k] = $v;
                     } else {
                         unset($val[$k]);
                     }
                 }
                 $val = array_values($val);
                 $this->duplicateBorder($val);
                 $this->value['padding']['t'] = $this->cssConverter->convertToMM($val[0], 0);
                 $this->value['padding']['r'] = $this->cssConverter->convertToMM($val[1], 0);
                 $this->value['padding']['b'] = $this->cssConverter->convertToMM($val[2], 0);
                 $this->value['padding']['l'] = $this->cssConverter->convertToMM($val[3], 0);
                 break;
             case 'padding-top':
                 $this->value['padding']['t'] = $this->cssConverter->convertToMM($val, 0);
                 break;
             case 'padding-right':
                 $this->value['padding']['r'] = $this->cssConverter->convertToMM($val, 0);
                 break;
             case 'padding-bottom':
                 $this->value['padding']['b'] = $this->cssConverter->convertToMM($val, 0);
                 break;
             case 'padding-left':
                 $this->value['padding']['l'] = $this->cssConverter->convertToMM($val, 0);
                 break;
             case 'margin':
                 if ($val == 'auto') {
                     $this->value['margin-auto'] = true;
                     break;
                 }
                 $val = explode(' ', $val);
                 foreach ($val as $k => $v) {
                     $v = trim($v);
                     if ($v != '') {
                         $val[$k] = $v;
                     } else {
                         unset($val[$k]);
                     }
                 }
                 $val = array_values($val);
                 $this->duplicateBorder($val);
                 $this->value['margin']['t'] = $this->cssConverter->convertToMM($val[0], 0);
                 $this->value['margin']['r'] = $this->cssConverter->convertToMM($val[1], 0);
                 $this->value['margin']['b'] = $this->cssConverter->convertToMM($val[2], 0);
                 $this->value['margin']['l'] = $this->cssConverter->convertToMM($val[3], 0);
                 break;
             case 'margin-top':
                 $this->value['margin']['t'] = $this->cssConverter->convertToMM($val, 0);
                 break;
             case 'margin-right':
                 $this->value['margin']['r'] = $this->cssConverter->convertToMM($val, 0);
                 break;
             case 'margin-bottom':
                 $this->value['margin']['b'] = $this->cssConverter->convertToMM($val, 0);
                 break;
             case 'margin-left':
                 $this->value['margin']['l'] = $this->cssConverter->convertToMM($val, 0);
                 break;
             case 'border':
                 $val = $this->readBorder($val);
                 $this->value['border']['t'] = $val;
                 $this->value['border']['r'] = $val;
                 $this->value['border']['b'] = $val;
                 $this->value['border']['l'] = $val;
                 break;
             case 'border-style':
                 $val = explode(' ', $val);
                 foreach ($val as $valK => $valV) {
                     if (!in_array($valV, array('solid', 'dotted', 'dashed'))) {
                         $val[$valK] = null;
                     }
                 }
                 $this->duplicateBorder($val);
                 if ($val[0]) {
                     $this->value['border']['t']['type'] = $val[0];
                 }
                 if ($val[1]) {
                     $this->value['border']['r']['type'] = $val[1];
                 }
                 if ($val[2]) {
                     $this->value['border']['b']['type'] = $val[2];
                 }
                 if ($val[3]) {
                     $this->value['border']['l']['type'] = $val[3];
                 }
                 break;
             case 'border-top-style':
                 if (in_array($val, array('solid', 'dotted', 'dashed'))) {
                     $this->value['border']['t']['type'] = $val;
                 }
                 break;
             case 'border-right-style':
                 if (in_array($val, array('solid', 'dotted', 'dashed'))) {
                     $this->value['border']['r']['type'] = $val;
                 }
                 break;
             case 'border-bottom-style':
                 if (in_array($val, array('solid', 'dotted', 'dashed'))) {
                     $this->value['border']['b']['type'] = $val;
                 }
                 break;
             case 'border-left-style':
                 if (in_array($val, array('solid', 'dotted', 'dashed'))) {
                     $this->value['border']['l']['type'] = $val;
                 }
                 break;
             case 'border-color':
                 $res = false;
                 $val = preg_replace('/,[\\s]+/', ',', $val);
                 $val = explode(' ', $val);
                 foreach ($val as $valK => $valV) {
                     $val[$valK] = $this->cssConverter->convertToColor($valV, $res);
                     if (!$res) {
                         $val[$valK] = null;
                     }
                 }
                 $this->duplicateBorder($val);
                 if (is_array($val[0])) {
                     $this->value['border']['t']['color'] = $val[0];
                 }
                 if (is_array($val[1])) {
                     $this->value['border']['r']['color'] = $val[1];
                 }
                 if (is_array($val[2])) {
                     $this->value['border']['b']['color'] = $val[2];
                 }
                 if (is_array($val[3])) {
                     $this->value['border']['l']['color'] = $val[3];
                 }
                 break;
             case 'border-top-color':
                 $res = false;
                 $val = $this->cssConverter->convertToColor($val, $res);
                 if ($res) {
                     $this->value['border']['t']['color'] = $val;
                 }
                 break;
             case 'border-right-color':
                 $res = false;
                 $val = $this->cssConverter->convertToColor($val, $res);
                 if ($res) {
                     $this->value['border']['r']['color'] = $val;
                 }
                 break;
             case 'border-bottom-color':
                 $res = false;
                 $val = $this->cssConverter->convertToColor($val, $res);
                 if ($res) {
                     $this->value['border']['b']['color'] = $val;
                 }
                 break;
             case 'border-left-color':
                 $res = false;
                 $val = $this->cssConverter->convertToColor($val, $res);
                 if ($res) {
                     $this->value['border']['l']['color'] = $val;
                 }
                 break;
             case 'border-width':
                 $val = explode(' ', $val);
                 foreach ($val as $valK => $valV) {
                     $val[$valK] = $this->cssConverter->convertToMM($valV, 0);
                 }
                 $this->duplicateBorder($val);
                 if ($val[0]) {
                     $this->value['border']['t']['width'] = $val[0];
                 }
                 if ($val[1]) {
                     $this->value['border']['r']['width'] = $val[1];
                 }
                 if ($val[2]) {
                     $this->value['border']['b']['width'] = $val[2];
                 }
                 if ($val[3]) {
                     $this->value['border']['l']['width'] = $val[3];
                 }
                 break;
             case 'border-top-width':
                 $val = $this->cssConverter->convertToMM($val, 0);
                 if ($val) {
                     $this->value['border']['t']['width'] = $val;
                 }
                 break;
             case 'border-right-width':
                 $val = $this->cssConverter->convertToMM($val, 0);
                 if ($val) {
                     $this->value['border']['r']['width'] = $val;
                 }
                 break;
             case 'border-bottom-width':
                 $val = $this->cssConverter->convertToMM($val, 0);
                 if ($val) {
                     $this->value['border']['b']['width'] = $val;
                 }
                 break;
             case 'border-left-width':
                 $val = $this->cssConverter->convertToMM($val, 0);
                 if ($val) {
                     $this->value['border']['l']['width'] = $val;
                 }
                 break;
             case 'border-collapse':
                 if ($tagName == 'table') {
                     $this->value['border']['collapse'] = $val == 'collapse';
                 }
                 break;
             case 'border-radius':
                 $val = explode('/', $val);
                 if (count($val) > 2) {
                     break;
                 }
                 $valH = $this->cssConverter->convertToRadius(trim($val[0]));
                 if (count($valH) < 1 || count($valH) > 4) {
                     break;
                 }
                 if (!isset($valH[1])) {
                     $valH[1] = $valH[0];
                 }
                 if (!isset($valH[2])) {
                     $valH = array($valH[0], $valH[0], $valH[1], $valH[1]);
                 }
                 if (!isset($valH[3])) {
                     $valH[3] = $valH[1];
                 }
                 if (isset($val[1])) {
                     $valV = $this->cssConverter->convertToRadius(trim($val[1]));
                     if (count($valV) < 1 || count($valV) > 4) {
                         break;
                     }
                     if (!isset($valV[1])) {
                         $valV[1] = $valV[0];
                     }
                     if (!isset($valV[2])) {
                         $valV = array($valV[0], $valV[0], $valV[1], $valV[1]);
                     }
                     if (!isset($valV[3])) {
                         $valV[3] = $valV[1];
                     }
                 } else {
                     $valV = $valH;
                 }
                 $this->value['border']['radius'] = array('tl' => array($valH[0], $valV[0]), 'tr' => array($valH[1], $valV[1]), 'br' => array($valH[2], $valV[2]), 'bl' => array($valH[3], $valV[3]));
                 break;
             case 'border-top-left-radius':
                 $val = $this->cssConverter->convertToRadius($val);
                 if (count($val) < 1 || count($val) > 2) {
                     break;
                 }
                 $this->value['border']['radius']['tl'] = array($val[0], isset($val[1]) ? $val[1] : $val[0]);
                 break;
             case 'border-top-right-radius':
                 $val = $this->cssConverter->convertToRadius($val);
                 if (count($val) < 1 || count($val) > 2) {
                     break;
                 }
                 $this->value['border']['radius']['tr'] = array($val[0], isset($val[1]) ? $val[1] : $val[0]);
                 break;
             case 'border-bottom-right-radius':
                 $val = $this->cssConverter->convertToRadius($val);
                 if (count($val) < 1 || count($val) > 2) {
                     break;
                 }
                 $this->value['border']['radius']['br'] = array($val[0], isset($val[1]) ? $val[1] : $val[0]);
                 break;
             case 'border-bottom-left-radius':
                 $val = $this->cssConverter->convertToRadius($val);
                 if (count($val) < 1 || count($val) > 2) {
                     break;
                 }
                 $this->value['border']['radius']['bl'] = array($val[0], isset($val[1]) ? $val[1] : $val[0]);
                 break;
             case 'border-top':
                 $this->value['border']['t'] = $this->readBorder($val);
                 break;
             case 'border-right':
                 $this->value['border']['r'] = $this->readBorder($val);
                 break;
             case 'border-bottom':
                 $this->value['border']['b'] = $this->readBorder($val);
                 break;
             case 'border-left':
                 $this->value['border']['l'] = $this->readBorder($val);
                 break;
             case 'background-color':
                 $this->value['background']['color'] = $this->cssConverter->convertBackgroundColor($val);
                 break;
             case 'background-image':
                 $this->value['background']['image'] = $this->cssConverter->convertBackgroundImage($val);
                 break;
             case 'background-position':
                 $res = null;
                 $this->value['background']['position'] = $this->cssConverter->convertBackgroundPosition($val, $res);
                 break;
             case 'background-repeat':
                 $this->value['background']['repeat'] = $this->cssConverter->convertBackgroundRepeat($val);
                 break;
             case 'background':
                 $this->cssConverter->convertBackground($val, $this->value['background']);
                 break;
             case 'position':
                 if ($val == 'absolute') {
                     $this->value['position'] = 'absolute';
                 } elseif ($val == 'relative') {
                     $this->value['position'] = 'relative';
                 } else {
                     $this->value['position'] = null;
                 }
                 break;
             case 'float':
                 if ($val == 'left') {
                     $this->value['float'] = 'left';
                 } elseif ($val == 'right') {
                     $this->value['float'] = 'right';
                 } else {
                     $this->value['float'] = null;
                 }
                 break;
             case 'display':
                 if ($val == 'inline') {
                     $this->value['display'] = 'inline';
                 } elseif ($val == 'block') {
                     $this->value['display'] = 'block';
                 } elseif ($val == 'none') {
                     $this->value['display'] = 'none';
                 } else {
                     $this->value['display'] = null;
                 }
                 break;
             case 'top':
             case 'bottom':
             case 'left':
             case 'right':
                 $this->value[$nom] = $val;
                 break;
             case 'list-style':
             case 'list-style-type':
             case 'list-style-image':
                 if ($nom == 'list-style') {
                     $nom = 'list-style-type';
                 }
                 $this->value[$nom] = $val;
                 break;
             case 'start':
                 $this->value[$nom] = intval($val);
                 break;
             default:
                 break;
         }
     }
     $return = true;
     // only for P tag
     if ($this->value['margin']['t'] === null) {
         $this->value['margin']['t'] = $this->value['font-size'];
     }
     if ($this->value['margin']['b'] === null) {
         $this->value['margin']['b'] = $this->value['font-size'];
     }
     // force the text align to left, if asked by html2pdf
     if ($this->onlyLeft) {
         $this->value['text-align'] = 'left';
     }
     // correction on the width (quick box)
     if ($noWidth && in_array($tagName, array('div', 'blockquote', 'fieldset')) && $this->value['position'] != 'absolute') {
         $this->value['width'] = $this->getLastWidth();
         $this->value['width'] -= $this->value['margin']['l'] + $this->value['margin']['r'];
     } else {
         if ($correctWidth) {
             if (!in_array($tagName, array('table', 'div', 'blockquote', 'fieldset', 'hr'))) {
                 $this->value['width'] -= $this->value['padding']['l'] + $this->value['padding']['r'];
                 $this->value['width'] -= $this->value['border']['l']['width'] + $this->value['border']['r']['width'];
             }
             if (in_array($tagName, array('th', 'td'))) {
                 $this->value['width'] -= $this->cssConverter->convertToMM(isset($param['cellspacing']) ? $param['cellspacing'] : '2px');
                 $return = false;
             }
             if ($this->value['width'] < 0) {
                 $this->value['width'] = 0;
             }
         } else {
             if ($this->value['width']) {
                 if ($this->value['border']['l']['width']) {
                     $this->value['width'] += $this->value['border']['l']['width'];
                 }
                 if ($this->value['border']['r']['width']) {
                     $this->value['width'] += $this->value['border']['r']['width'];
                 }
                 if ($this->value['padding']['l']) {
                     $this->value['width'] += $this->value['padding']['l'];
                 }
                 if ($this->value['padding']['r']) {
                     $this->value['width'] += $this->value['padding']['r'];
                 }
             }
         }
     }
     if ($this->value['height']) {
         if ($this->value['border']['b']['width']) {
             $this->value['height'] += $this->value['border']['b']['width'];
         }
         if ($this->value['border']['t']['width']) {
             $this->value['height'] += $this->value['border']['t']['width'];
         }
         if ($this->value['padding']['b']) {
             $this->value['height'] += $this->value['padding']['b'];
         }
         if ($this->value['padding']['t']) {
             $this->value['height'] += $this->value['padding']['t'];
         }
     }
     if ($this->value['top'] != null) {
         $this->value['top'] = $this->cssConverter->convertToMM($this->value['top'], $this->getLastHeight(true));
     }
     if ($this->value['bottom'] != null) {
         $this->value['bottom'] = $this->cssConverter->convertToMM($this->value['bottom'], $this->getLastHeight(true));
     }
     if ($this->value['left'] != null) {
         $this->value['left'] = $this->cssConverter->convertToMM($this->value['left'], $this->getLastWidth(true));
     }
     if ($this->value['right'] != null) {
         $this->value['right'] = $this->cssConverter->convertToMM($this->value['right'], $this->getLastWidth(true));
     }
     if ($this->value['top'] && $this->value['bottom'] && $this->value['height']) {
         $this->value['bottom'] = null;
     }
     if ($this->value['left'] && $this->value['right'] && $this->value['width']) {
         $this->value['right'] = null;
     }
     return $return;
 }