/** * * get tag and attrs * @param string $value */ public function getTagData($value) { $mixed = $this->getInstance("Fl_Html_TagToken", $value)->run(); $attrs = $mixed['attrs']; $data = array($this->options['tag'] => $mixed['tag']); if (!empty($attrs)) { foreach ($attrs as $aItem) { $count = count($aItem); if ($count === 1) { $attrsData[$aItem[0]] = ""; } elseif ($count === 3) { if ($this->options['attrs_remove_quote']) { $valueDetail = Fl_Html_Static::getUnquoteText($aItem[2]); $attrsData[$aItem[0]] = $valueDetail['text']; } else { $attrsData[$aItem[0]] = $aItem[2]; } } } $data[$this->options['attrs']] = $attrsData; } return $data; }
/** * * 压缩开始标签 */ public function compressStartTag($token) { if ($this->isXML) { return $token['value']; } $tag = $token['tag']; $lowerTag = $token['lowerTag']; $attrs = $token['attrs']; $resultAttrs = array(); foreach ($attrs as $item) { if ($item[1] === '=') { $valueDetail = Fl_Html_Static::getUnquoteText($item[2]); if ($this->options['removeAttrDefaultValue'] && Fl_Html_Static::isTagAttrDefaultValue($item[0], $valueDetail['text'], $lowerTag)) { continue; } if ($this->options['attrOnlyName'] && Fl_Html_Static::isTagOnlyNameAttr($item[0])) { $item = array($item[0]); } else { if ($this->options['removeAttrQuote'] && Fl_Html_Static::isAttrValueNoQuote($valueDetail['text'], $this)) { $item[2] = $valueDetail['text']; } } } $resultAttrs[] = $item; } $return = Fl_Html_Static::LEFT; if ($this->options['tagToLower']) { $return .= $lowerTag; } else { $return .= $tag; } $blankChar = ' '; $return .= $blankChar; foreach ($resultAttrs as $item) { $itemText = join('', $item); $lastChar = substr($return, strlen($return) - 1); if ($lastChar !== '"' && $lastChar !== "'" && $lastChar !== $blankChar) { if ($item[1] !== '=' && $this->isTpl($item[0]) && !$this->checkTplHasOutput($item[0])) { //do nothing } else { $return .= $blankChar; } } $return .= $itemText; } if ($this->options['endSingleTag'] && Fl_Html_Static::isSingleTag($lowerTag)) { $lastChar = substr($return, strlen($return) - 1); if ($lastChar !== '"' && $lastChar !== "'" && $lastChar !== $blankChar) { $return .= $blankChar; } $return .= '/'; } $return = rtrim($return); $return .= Fl_Html_Static::RIGHT; return $return; }
/** * * 过滤开始标签 * @param array $token */ public function filterTag($token, $notCheckECss = false) { $value = $token['value']; if (!empty($value)) { $instance = $this->getInstance('Fl_Html_TagToken', $value); $result = $instance->run(); } else { $result = $token; } $tag = strtolower($result['tag']); //外链的css if (!$notCheckECss && $this->isExternalCss($result)) { return $this->filterExternalCss($result); } if ($this->options['use_blank_tag_filter']) { if (!in_array($tag, $this->blankTagList)) { return false; } } $attrs = $result['attrs']; $attrResult = array(); foreach ($attrs as $item) { $name = strtolower($item[0]); //过滤事件 if ($this->options['remove_tag_event']) { if (strpos($name, 'on') === 0) { continue; } } //标签属性白名单 if ($this->options['use_blank_tag_property_filter']) { if (!in_array($name, $this->blankTagPropertyList)) { //标签的特殊属性过滤 if ($this->options['use_special_tag_filter']) { if (isset($this->allowSpecialTagProperty[$tag])) { $propList = $this->allowSpecialTagProperty[$tag]; if (isset($propList[$name])) { $value = $propList[$name]; $values = Fl_Html_Static::getUnquoteText($item[2]); //正则 if (substr($value, 0, 1) === '/') { if (preg_match($value, $values['text'])) { $attrResult[] = $item; } } else { if ($value === $values['text']) { $attrResult[] = $item; } } } } } continue; } } //a链接修复和过滤 if ($tag == 'a' && $this->options['filter_a_href_value'] && $name == 'href') { if (count($item) == 3 && $item[1] == '=') { $values = Fl_Html_Static::getUnquoteText($item[2]); $url = Fl_Static::getFixedUrl($values['text'], $this->url); if ($this->options['url_max_length']) { $url = substr($url, 0, $this->options['url_max_length']); } $item[2] = $values['quote'] . $url . $values['quote']; } else { continue; } } //图片连接的修复和过滤 if ($tag == 'img' && $this->options['filter_img_src_value'] && $name == 'src') { if (count($item) == 3 && $item[1] == '=') { $values = Fl_Html_Static::getUnquoteText($item[2]); $url = Fl_Static::getFixedUrl($values['text'], $this->url); if ($this->options['url_max_length']) { $url = substr($url, 0, $this->options['url_max_length']); } $item[2] = $values['quote'] . $url . $values['quote']; } else { continue; } } //style value if ($this->options['filter_tag_style_value'] && $name == 'style') { if (count($item) == 3 && $item[1] == '=') { $values = Fl_Html_Static::getUnquoteText($item[2]); $text = 'a{' . $values['text'] . '}'; $instance = $this->getInstance("Fl_Css_Filter", $text); $instance->url = $this->url; $instance->getResourceContentFn = $this->getResourceContentFn; $text = $instance->run($this->options); $item[2] = $values['quote'] . substr($text, 2, strlen($text) - 3) . $values['quote']; } else { continue; } } $attrResult[] = $item; } $attrsJoin = array(); foreach ($attrResult as $item) { $attrsJoin[] = join("", $item); } if (empty($attrsJoin)) { return '<' . $tag . '>'; } return '<' . $tag . ' ' . join(" ", $attrsJoin) . ">"; }
/** * * 压缩开始标签 */ public function compressStartTag($token) { if ($this->isXML || !$this->options['compress_tag']) { return $token['value']; } $tag = $token['tag']; $lowerTag = $token['lowerTag']; if ($lowerTag === 'meta' && $this->options['simple_charset']) { $result = $this->compressCharset($token); if ($result) { return $result; } } $attrs = $token['attrs']; $resultAttrs = array(); foreach ($attrs as $item) { if ($item[1] === '=') { $valueDetail = Fl_Html_Static::getUnquoteText($item[2]); $nameLower = strtolower($item[0]); if ($this->options['remove_optional_attrs'] && Fl_Html_Static::isTagAttrDefaultValue($item[0], $valueDetail['text'], $lowerTag)) { continue; } if ($this->options['remove_attrs_optional_value'] && Fl_Html_Static::isTagOnlyNameAttr($item[0])) { $item = array($item[0]); } else { if ($this->options['remove_attrs_quote'] && Fl_Html_Static::isAttrValueNoQuote($valueDetail['text'], $this)) { if ($nameLower != 'style') { $item[2] = $valueDetail['text']; $valueDetail['quote'] = ''; } } } //$nameLower = strtolower ( $item [0] ); //remove html xmlns attr if ($lowerTag === 'html' && $nameLower === 'xmlns' && $this->options['remove_html_xmlns']) { continue; } if ($this->options['remove_http_protocal'] || $this->options['remove_https_protocal']) { if ($nameLower === 'href' || $nameLower === "src") { $valueDetail = Fl_Html_Static::getUnquoteText($item[2]); $value = $valueDetail['text']; if ($this->options['remove_http_protocal'] && strpos($value, "http://") === 0) { $value = substr($value, 5); $item[2] = $valueDetail['quote'] . $value . $valueDetail['quote']; } elseif ($this->options['remove_https_protocal'] && strpos($value, "https://") === 0) { $value = substr($value, 6); $item[2] = $valueDetail['quote'] . $value . $valueDetail['quote']; } } } //$valueDetail = Fl_Html_Static::getUnquoteText ( $item [2] ); //remove ext blank in class value if ($nameLower === 'class' && !$this->containTpl($item[2])) { $value = trim($valueDetail['text']); $value = preg_split(FL_SPACE_PATTERN, $value); $item[2] = $valueDetail['quote'] . join(FL_SPACE, $value) . $valueDetail['quote']; } else { if ($this->options['compress_style_value'] && $nameLower === 'style' && !$this->containTpl($valueDetail["text"])) { //如果压缩失败,则直接使用源代码 try { if ($this->cssCompressMethod) { $value = call_user_func($this->cssCompressMethod, "*{" . $valueDetail["text"] . "}", $this); } else { $value = $this->getInstance("Fl_Css_Compress", "*{" . $valueDetail["text"] . "}")->run(); } $item[2] = $valueDetail['quote'] . substr($value, 2, strlen($value) - 3) . $valueDetail['quote']; } catch (Fl_Exception $e) { //这里不抛出异常 } } else { if (strpos($nameLower, "on") === 0) { //remove last ; in onxxx attr $value = trim(trim($valueDetail['text']), ';'); $item[2] = $valueDetail['quote'] . $value . $valueDetail['quote']; } } } } $resultAttrs[] = $item; } $return = Fl_Html_Static::LEFT; if ($this->options['tag_to_lower']) { $return .= $lowerTag; } else { $return .= $tag; } $blankChar = FL_SPACE; $return .= $blankChar; foreach ($resultAttrs as $item) { $itemText = join('', $item); $lastChar = substr($return, strlen($return) - 1); if ($lastChar !== '"' && $lastChar !== "'" && $lastChar !== $blankChar) { if ($item[1] !== '=' && $this->isTpl($item[0]) && !$this->checkTplHasOutput($item[0])) { //do nothing } else { $return .= $blankChar; } } else { $last2Char = substr($return, strlen($return) - 2); if ($last2Char === '\\"' || $last2Char === "\\'") { $return .= $blankChar; } } $return .= $itemText; } $return = rtrim($return) . Fl_Html_Static::RIGHT; return $return; }
/** * * 获取特定属性的值 * @param array $attrs * @param string $name */ public static function getAttrValue($attrs, $name = '') { foreach ($attrs as $item) { if (count($item) === 3) { if (strtolower($item[0]) === $name) { $value = $item[2]; $valueInfo = Fl_Html_Static::getUnquoteText($value); return $valueInfo['text']; } } } return false; }