И сделал свои правки, основываясь на коде, который используется для вставок картинок. Получилось что-то такое:
/**
* Get all hyperlink nodes marked with placeholders.
* If $generateNewhyperlinkIds is true - will replace relation ids to new values.
*
* @param bool $generateNewHyperlinkIds
* @param \DOMNode|null $contextNode
* @return array
*/
public function findHyperlinks(bool $generateNewHyperlinkIds = false, \DOMNode $contextNode = null): array
{
$this->initDomDocument();
if($contextNode)
$HyperlinkDescriptions = $this->xpath->query('//w:hyperlink w:history', $contextNode);
}
else
{
$HyperlinkDescriptions = $this->xpath->query('//w:hyperlink w:history');
}
$placeholders = [];
foreach($HyperlinkDescriptions as $description)
{
/** @var \DOMElement $description */
if($description->hasAttributes())
{
$name = $description->attributes->getNamedItem('name');
$descr = $description->attributes->getNamedItem('descr');
$placeholder = null;
if($descr)
{
$placeholder = static::getCodeFromPlaceholder($descr->nodeValue);
}
if(!$placeholder && $name)
{
$placeholder = static::getCodeFromPlaceholder($name->nodeValue);
}
if($placeholder)
{
if(!isset($placeholders[$placeholder]))
{
$placeholders[$placeholder] = [
'hyperlinkNode' => [],
'innerIDs' => [],
];
}
$placeholders[$placeholder]['hyperlinkNode'][] = $description->parentNode->parentNode;
$embeds = $description->parentNode->getElementsByTagNameNS(static::getNamespaces()['a'], 'blip');
if($embeds->length > 0)
{
/** @var \DOMAttr $innerHyperlinkId */
$hyperlinkId = $innerhyperlinkId->value;
if($generateNewHyperlinkIds && !isset($this->arrayHyperlinkValues['originalId'][$hyperlinkId]))
{
$newHyperlinkId = static::getRandomId('rId', true);
$placeholders[$placeholder]['originalId'][$newHyperlinkId] = $HyperlinkId;
$HyperlinkId = $innerHyperlinkId->value = $newHyperlinkId;
}
if(!in_array($HyperlinkId, $placeholders[$placeholder]['innerIDs']))
{
$placeholders[$placeholder]['innerIDs'][] = $hyperlinkId;
if(isset($this->arrayHyperlinkValues['values'][$hyperlinkId]))
{
$placeholders[$placeholder]['values'][$hyperlinkId] = $this->arrayHyperlinkValues['values'][$hyperlinkId];
$placeholders[$placeholder]['originalId'][$hyperlinkId] = $this->arrayHyperlinkValues['originalId'][$hyperlinkId];
}
}
}
}
}
}
if(!empty($placeholders) && $generateNewHyperlinkIds)
{
$this->saveContent();
}
return $placeholders;
}
/**
* @param mixed $value
* @param string $placeholder
* @param string $modifier
* @param array $params
* @return string
*/
protected function printValue($value, $placeholder, $modifier = '', array $params = []): string
{
$value = parent::printValue($value, $placeholder, $modifier);
if(empty($value))
{
return (string) $value;
}
if (ToUpper(SITE_CHARSET) !== 'UTF-8')
{
if(is_array($value) || is_object($value))
{
$value = '';
}
elseif(!Encoding::detectUtf8($value))
{
$value = Encoding::convertEncoding($value, SITE_CHARSET, 'UTF-8');
}
}
if(is_string($value))
{
if($this->isHyperlinkValue($placeholder, $this->values))
{
return '';
}
if($this->isHtml($value))
{
$context = [];
if(isset($params['currentNode']) && $params['currentNode'] instanceof \DOMElement)
{
$context['rowProperties'] = $this->getRowPropertyNodeValue($params['currentNode']);
}
$value = $this->htmlToXml($value, $context);
}
else
{
$value = $this->prepareTextValue($value);
}
}
return $value;
}
/**
* @param string $placeholder
* @param array $values
* @param array|null $fields
* @return bool
*/
protected function isHyperlinkValue(string $placeholder, array $values, array $fields = null): bool
{
if(!$fields)
{
$fields = $this->fields;
}
return (
array_key_exists($placeholder, $values) &&
isset($fields[$placeholder]['TYPE']) &&
(
$fields[$placeholder]['TYPE'] === DataProvider::FIELD_TYPE_HYPERLINK
|| $fields[$placeholder]['TYPE'] === DataProvider::FIELD_TYPE_STAMP
)
);
}
/**
* @return string
*/
protected function getBreakLineTag(): string
{
return '</w:t><w:br/><w:t>';
}
/**
* @param $string
* @return bool
*/
protected function isHtml($string): bool
{
return (preg_match('/<\s?[^\>]*\/?\s?>/i', $string) != false);
}
/**
* Converts html to xml with the same rendering.
*
* @param string $html
* @param array $context
* @return string
*/
protected function htmlToXml(string $html, array $context = []): string
{
$htmlDocument = new DOM\Document();
$htmlDocument->loadHTML($html);
$result = $this->htmlNodeToXml($htmlDocument, $context);
if(!empty($result))
{
$result = '</w:t></w:r>'.$result.'<w:r><w:t>';
}
return $result;
}
/**
* @param DOM\Node $node
* @param array $properties
* @return DOM\DisplayProperties
*/
protected function getDisplayProperties(DOM\Node $node, array $properties = []): DOM\DisplayProperties
{
return new DOM\DisplayProperties($node, $properties);
}
/**
* Recursively converts html node to xml.
*
* @param DOM\Node $node
* @param array $context
* @return string
*/
protected function htmlNodeToXml(DOM\Node $node, array &$context = []): string
{
$result = '';
$this->deleteLastBreakLineInBlockTag($node);
$displayProperties = $this->getDisplayProperties($node);
if($displayProperties->isHidden())
{
return $result;
}
$nodes = $node->getChildNodes();
$nodeName = mb_strtolower($node->getNodeName());
if($nodeName === 'ul')
{
$context['currentList'] = [
'type' => static::NUMBERING_TYPE_UNORDERED,
'id' => $this->getRandomId('numberingValue', false),
];
}
elseif($nodeName === 'ol')
{
$context['currentList'] = [
'type' => static::NUMBERING_TYPE_ORDERED,
'id' => $this->getRandomId('numberingValue', false),
];
}
elseif($nodeName === 'li')
{
$context['showNumber'] = true;
}
if($displayProperties->isDisplayBlock())
{
$context['display'] = DOM\DisplayProperties::DISPLAY_BLOCK;
}
if(!isset($context['font']) || !is_array($context['font']))
{
$context['font'] = [];
}
$context['font'] = array_merge($context['font'], $displayProperties->getProperties()['font']);
// The trick is in order we get tags. We have to carry $context all along.
// First we have 'b' tag and then we have #text tag. But they are on the same level of hierarchy.
// So we have to put 'bold font' into context and we need to know about it in the next tag.
/** @var DOM\Node $childNode */
foreach($nodes as $childNode)
{
$nodeValue = str_replace("\n", '', $childNode->getNodeValue());
if($context['display'] === DOM\DisplayProperties::DISPLAY_BLOCK || $displayProperties->isDisplayBlock())
{
$nodeValue = trim($nodeValue);
}
$childNodeName = mb_strtolower($childNode->getNodeName());
if($childNodeName === 'br')
{
$result .= '<w:r>';
$result .= '<w:br/>';
$result .= '</w:r>';
}
elseif($childNode instanceof DOM\Text && !empty($nodeValue))
{
if(isset($context['showNumber']) && isset($context['currentList']))
{
$result .= '</w:p>';
$result .= '<w:p>';
$this->numberingIds[$context['currentList']['id']] = $context['currentList'];
$result .= '<w:pPr>';
$result .= '<w:numPr>';
$result .= '<w:ilvl w:val="0" />';
$result .= '<w:numId w:val="'.$context['currentList']['id'].'" />';
$result .= '</w:numPr>';
$result .= '</w:pPr>';
unset($context['showNumber']);
$context['display'] = $displayProperties->getProperties()[DOM\DisplayProperties::DISPLAY];
$result .= '<w:r>';
}
elseif($context['display'] === DOM\DisplayProperties::DISPLAY_BLOCK)
{
$result .= '<w:r>';
$result .= '<w:br/>';
$context['display'] = $displayProperties->getProperties()[DOM\DisplayProperties::DISPLAY];
}
else
{
$result .= '<w:r>';
}
$result .= $this->addRowPropertiesTag($context);
$result .= '<w:t xml:space="preserve">';
$result .= $this->prepareTextValue($nodeValue);
$result .= '</w:t>';
$result .= '</w:r>';
}
else
{
$result .= $this->htmlNodeToXml($childNode, $context);
}
}
if($nodeName === 'ul' || $nodeName === 'ol')
{
unset($context['currentList']);
$result .= '</w:p>';
$result .= '<w:p>';
}
elseif($nodeName === 'li')
{
unset($context['showNumber']);
}
$context['font'] = array_diff_assoc($context['font'], $displayProperties->getProperties()['font']);
return $result;
}
Все ли изменения я сделал и что еще нужно поменять в самом docxxml.php?И какой файл должен отвечать за передачу гиперссылок? БП мне генерирует ссылки вида:
[url=