AutorÃa | Ultima modificación | Ver Log |
<?php
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing;
use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
class Rels extends WriterPart
{
/**
* Write relationships to XML format.
*
* @return string XML Output
*/
public function writeRelationships(Spreadsheet $spreadsheet)
{
// Create XML writer
$objWriter = null;
if ($this->getParentWriter()->getUseDiskCaching()) {
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
} else {
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
}
// XML header
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
// Relationships
$objWriter->startElement('Relationships');
$objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
$customPropertyList = $spreadsheet->getProperties()->getCustomProperties();
if (!empty($customPropertyList)) {
// Relationship docProps/app.xml
$this->writeRelationship(
$objWriter,
4,
Namespaces::RELATIONSHIPS_CUSTOM_PROPERTIES,
'docProps/custom.xml'
);
}
// Relationship docProps/app.xml
$this->writeRelationship(
$objWriter,
3,
Namespaces::RELATIONSHIPS_EXTENDED_PROPERTIES,
'docProps/app.xml'
);
// Relationship docProps/core.xml
$this->writeRelationship(
$objWriter,
2,
Namespaces::CORE_PROPERTIES,
'docProps/core.xml'
);
// Relationship xl/workbook.xml
$this->writeRelationship(
$objWriter,
1,
Namespaces::OFFICE_DOCUMENT,
'xl/workbook.xml'
);
// a custom UI in workbook ?
$target = $spreadsheet->getRibbonXMLData('target');
if ($spreadsheet->hasRibbon()) {
$this->writeRelationShip(
$objWriter,
5,
Namespaces::EXTENSIBILITY,
is_string($target) ? $target : ''
);
}
$objWriter->endElement();
return $objWriter->getData();
}
/**
* Write workbook relationships to XML format.
*
* @return string XML Output
*/
public function writeWorkbookRelationships(Spreadsheet $spreadsheet)
{
// Create XML writer
$objWriter = null;
if ($this->getParentWriter()->getUseDiskCaching()) {
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
} else {
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
}
// XML header
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
// Relationships
$objWriter->startElement('Relationships');
$objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
// Relationship styles.xml
$this->writeRelationship(
$objWriter,
1,
Namespaces::STYLES,
'styles.xml'
);
// Relationship theme/theme1.xml
$this->writeRelationship(
$objWriter,
2,
Namespaces::THEME2,
'theme/theme1.xml'
);
// Relationship sharedStrings.xml
$this->writeRelationship(
$objWriter,
3,
Namespaces::SHARED_STRINGS,
'sharedStrings.xml'
);
// Relationships with sheets
$sheetCount = $spreadsheet->getSheetCount();
for ($i = 0; $i < $sheetCount; ++$i) {
$this->writeRelationship(
$objWriter,
($i + 1 + 3),
Namespaces::WORKSHEET,
'worksheets/sheet' . ($i + 1) . '.xml'
);
}
// Relationships for vbaProject if needed
// id : just after the last sheet
if ($spreadsheet->hasMacros()) {
$this->writeRelationShip(
$objWriter,
($i + 1 + 3),
Namespaces::VBA,
'vbaProject.bin'
);
++$i; //increment i if needed for an another relation
}
$objWriter->endElement();
return $objWriter->getData();
}
/**
* Write worksheet relationships to XML format.
*
* Numbering is as follows:
* rId1 - Drawings
* rId_hyperlink_x - Hyperlinks
*
* @param int $worksheetId
* @param bool $includeCharts Flag indicating if we should write charts
* @param int $tableRef Table ID
*
* @return string XML Output
*/
public function writeWorksheetRelationships(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet, $worksheetId = 1, $includeCharts = false, $tableRef = 1)
{
// Create XML writer
$objWriter = null;
if ($this->getParentWriter()->getUseDiskCaching()) {
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
} else {
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
}
// XML header
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
// Relationships
$objWriter->startElement('Relationships');
$objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
// Write drawing relationships?
$drawingOriginalIds = [];
$unparsedLoadedData = $worksheet->getParentOrThrow()->getUnparsedLoadedData();
if (isset($unparsedLoadedData['sheets'][$worksheet->getCodeName()]['drawingOriginalIds'])) {
$drawingOriginalIds = $unparsedLoadedData['sheets'][$worksheet->getCodeName()]['drawingOriginalIds'];
}
if ($includeCharts) {
$charts = $worksheet->getChartCollection();
} else {
$charts = [];
}
if (($worksheet->getDrawingCollection()->count() > 0) || (count($charts) > 0) || $drawingOriginalIds) {
$rId = 1;
// Use original $relPath to get original $rId.
// Take first. In future can be overwritten.
// (! synchronize with \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Worksheet::writeDrawings)
reset($drawingOriginalIds);
$relPath = key($drawingOriginalIds);
if (isset($drawingOriginalIds[$relPath])) {
$rId = (int) (substr($drawingOriginalIds[$relPath], 3));
}
// Generate new $relPath to write drawing relationship
$relPath = '../drawings/drawing' . $worksheetId . '.xml';
$this->writeRelationship(
$objWriter,
$rId,
Namespaces::RELATIONSHIPS_DRAWING,
$relPath
);
}
// Write hyperlink relationships?
$i = 1;
foreach ($worksheet->getHyperlinkCollection() as $hyperlink) {
if (!$hyperlink->isInternal()) {
$this->writeRelationship(
$objWriter,
'_hyperlink_' . $i,
Namespaces::HYPERLINK,
$hyperlink->getUrl(),
'External'
);
++$i;
}
}
// Write comments relationship?
$i = 1;
if (count($worksheet->getComments()) > 0 || isset($unparsedLoadedData['sheets'][$worksheet->getCodeName()]['legacyDrawing'])) {
$this->writeRelationship(
$objWriter,
'_comments_vml' . $i,
Namespaces::VML,
'../drawings/vmlDrawing' . $worksheetId . '.vml'
);
}
if (count($worksheet->getComments()) > 0) {
$this->writeRelationship(
$objWriter,
'_comments' . $i,
Namespaces::COMMENTS,
'../comments' . $worksheetId . '.xml'
);
}
// Write Table
$tableCount = $worksheet->getTableCollection()->count();
for ($i = 1; $i <= $tableCount; ++$i) {
$this->writeRelationship(
$objWriter,
'_table_' . $i,
Namespaces::RELATIONSHIPS_TABLE,
'../tables/table' . $tableRef++ . '.xml'
);
}
// Write header/footer relationship?
$i = 1;
if (count($worksheet->getHeaderFooter()->getImages()) > 0) {
$this->writeRelationship(
$objWriter,
'_headerfooter_vml' . $i,
Namespaces::VML,
'../drawings/vmlDrawingHF' . $worksheetId . '.vml'
);
}
$this->writeUnparsedRelationship($worksheet, $objWriter, 'ctrlProps', Namespaces::RELATIONSHIPS_CTRLPROP);
$this->writeUnparsedRelationship($worksheet, $objWriter, 'vmlDrawings', Namespaces::VML);
$this->writeUnparsedRelationship($worksheet, $objWriter, 'printerSettings', Namespaces::RELATIONSHIPS_PRINTER_SETTINGS);
$objWriter->endElement();
return $objWriter->getData();
}
private function writeUnparsedRelationship(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet, XMLWriter $objWriter, string $relationship, string $type): void
{
$unparsedLoadedData = $worksheet->getParentOrThrow()->getUnparsedLoadedData();
if (!isset($unparsedLoadedData['sheets'][$worksheet->getCodeName()][$relationship])) {
return;
}
foreach ($unparsedLoadedData['sheets'][$worksheet->getCodeName()][$relationship] as $rId => $value) {
if (substr($rId, 0, 17) !== '_headerfooter_vml') {
$this->writeRelationship(
$objWriter,
$rId,
$type,
$value['relFilePath']
);
}
}
}
/**
* Write drawing relationships to XML format.
*
* @param int $chartRef Chart ID
* @param bool $includeCharts Flag indicating if we should write charts
*
* @return string XML Output
*/
public function writeDrawingRelationships(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet, &$chartRef, $includeCharts = false)
{
// Create XML writer
$objWriter = null;
if ($this->getParentWriter()->getUseDiskCaching()) {
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
} else {
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
}
// XML header
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
// Relationships
$objWriter->startElement('Relationships');
$objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
// Loop through images and write relationships
$i = 1;
$iterator = $worksheet->getDrawingCollection()->getIterator();
while ($iterator->valid()) {
$drawing = $iterator->current();
if (
$drawing instanceof \PhpOffice\PhpSpreadsheet\Worksheet\Drawing
|| $drawing instanceof MemoryDrawing
) {
// Write relationship for image drawing
$this->writeRelationship(
$objWriter,
$i,
Namespaces::IMAGE,
'../media/' . $drawing->getIndexedFilename()
);
$i = $this->writeDrawingHyperLink($objWriter, $drawing, $i);
}
$iterator->next();
++$i;
}
if ($includeCharts) {
// Loop through charts and write relationships
$chartCount = $worksheet->getChartCount();
if ($chartCount > 0) {
for ($c = 0; $c < $chartCount; ++$c) {
$this->writeRelationship(
$objWriter,
$i++,
Namespaces::RELATIONSHIPS_CHART,
'../charts/chart' . ++$chartRef . '.xml'
);
}
}
}
$objWriter->endElement();
return $objWriter->getData();
}
/**
* Write header/footer drawing relationships to XML format.
*
* @return string XML Output
*/
public function writeHeaderFooterDrawingRelationships(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet)
{
// Create XML writer
$objWriter = null;
if ($this->getParentWriter()->getUseDiskCaching()) {
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
} else {
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
}
// XML header
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
// Relationships
$objWriter->startElement('Relationships');
$objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
// Loop through images and write relationships
foreach ($worksheet->getHeaderFooter()->getImages() as $key => $value) {
// Write relationship for image drawing
$this->writeRelationship(
$objWriter,
$key,
Namespaces::IMAGE,
'../media/' . $value->getIndexedFilename()
);
}
$objWriter->endElement();
return $objWriter->getData();
}
public function writeVMLDrawingRelationships(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet): string
{
// Create XML writer
$objWriter = null;
if ($this->getParentWriter()->getUseDiskCaching()) {
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
} else {
$objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
}
// XML header
$objWriter->startDocument('1.0', 'UTF-8', 'yes');
// Relationships
$objWriter->startElement('Relationships');
$objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
// Loop through images and write relationships
foreach ($worksheet->getComments() as $comment) {
if (!$comment->hasBackgroundImage()) {
continue;
}
$bgImage = $comment->getBackgroundImage();
$this->writeRelationship(
$objWriter,
$bgImage->getImageIndex(),
Namespaces::IMAGE,
'../media/' . $bgImage->getMediaFilename()
);
}
$objWriter->endElement();
return $objWriter->getData();
}
/**
* Write Override content type.
*
* @param int|string $id Relationship ID. rId will be prepended!
* @param string $type Relationship type
* @param string $target Relationship target
* @param string $targetMode Relationship target mode
*/
private function writeRelationship(XMLWriter $objWriter, $id, $type, $target, $targetMode = ''): void
{
if ($type != '' && $target != '') {
// Write relationship
$objWriter->startElement('Relationship');
$objWriter->writeAttribute('Id', 'rId' . $id);
$objWriter->writeAttribute('Type', $type);
$objWriter->writeAttribute('Target', $target);
if ($targetMode != '') {
$objWriter->writeAttribute('TargetMode', $targetMode);
}
$objWriter->endElement();
} else {
throw new WriterException('Invalid parameters passed.');
}
}
private function writeDrawingHyperLink(XMLWriter $objWriter, BaseDrawing $drawing, int $i): int
{
if ($drawing->getHyperlink() === null) {
return $i;
}
++$i;
$this->writeRelationship(
$objWriter,
$i,
Namespaces::HYPERLINK,
$drawing->getHyperlink()->getUrl(),
$drawing->getHyperlink()->getTypeHyperlink()
);
return $i;
}
}