diff --git a/CHANGELOG.md b/CHANGELOG.md index 5290ccb3..28c646ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ This is the changelog between releases of PHPWord. Releases are listed in revers ## 0.12.0 - Not yet released -This release added drawing shapes (arc, curve, line, polyline, rect, oval) element and some new styles. +This release added drawing shapes (arc, curve, line, polyline, rect, oval) and basic 2D chart (pie, doughnut, bar, line, area, scatter, radar) elements along with some new styles. ### Features @@ -15,6 +15,7 @@ This release added drawing shapes (arc, curve, line, polyline, rect, oval) eleme - Section: Ability to set paper size, e.g. A4, A3, and Legal - @ivanlanin GH-249 - General: New `PhpWord::save()` method to encapsulate `IOFactory` - @ivanlanin - General: New `Shared\Converter` static class - @ivanlanin +- Element: Basic 2D chart (pie, doughnut, bar, line, area, scatter, radar) - @ivanlanin GH-278 ### Bugfixes diff --git a/README.md b/README.md index 97e5b642..5a432cba 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,8 @@ With PHPWord, you can create DOCX, ODT, or RTF documents dynamically using your - Insert list items as bulleted, numbered, or multilevel - Insert hyperlinks - Insert footnotes and endnotes +- Insert drawing shapes (arc, curve, line, polyline, rect, oval) +- Insert charts (pie, doughnut, bar, line, area, scatter, radar) - Create document from templates - Use XSL 1.0 style sheets to transform main document part of OOXML template - ... and many more features on progress diff --git a/docs/elements.rst b/docs/elements.rst index a01c9fd4..ee827326 100644 --- a/docs/elements.rst +++ b/docs/elements.rst @@ -49,6 +49,8 @@ column shows the containers while the rows lists the elements. +-------+-----------------+-----------+----------+----------+---------+------------+------------+ | 20 | Shape | v | v | v | v | v | v | +-------+-----------------+-----------+----------+----------+---------+------------+------------+ +| 21 | Chart | v | - | - | - | - | - | ++-------+-----------------+-----------+----------+----------+---------+------------+------------+ Legend: @@ -399,3 +401,8 @@ Shapes ------ To be completed. + +Charts +------ + +To be completed. diff --git a/docs/intro.rst b/docs/intro.rst index 5045d4dc..241b581c 100644 --- a/docs/intro.rst +++ b/docs/intro.rst @@ -45,6 +45,8 @@ Features - Insert list items as bulleted, numbered, or multilevel - Insert hyperlinks - Insert footnotes and endnotes +- Insert drawing shapes (arc, curve, line, polyline, rect, oval) +- Insert charts (pie, doughnut, bar, line, area, scatter, radar) - Create document from templates - Use XSL 1.0 style sheets to transform main document part of OOXML template diff --git a/docs/src/documentation.md b/docs/src/documentation.md index 6ad2f67a..39e61862 100644 --- a/docs/src/documentation.md +++ b/docs/src/documentation.md @@ -37,6 +37,7 @@ Don't forget to change `code::` directive to `code-block::` in the resulting rst - [Fields](#fields) - [Lines](#lines) - [Shapes](#shapes) + - [Charts](#charts) - [Styles](#styles) - [Section](#section) - [Font](#font) @@ -76,6 +77,8 @@ PHPWord is an open source project licensed under the terms of [LGPL version 3](h - Insert list items as bulleted, numbered, or multilevel - Insert hyperlinks - Insert footnotes and endnotes +- Insert drawing shapes (arc, curve, line, polyline, rect, oval) +- Insert charts (pie, doughnut, bar, line, area, scatter, radar) - Create document from templates - Use XSL 1.0 style sheets to transform main document part of OOXML template - ... and many more features on progress @@ -440,6 +443,7 @@ Below are the matrix of element availability in each container. The column shows | 18 | Field | v | v | v | v | v | v | | 19 | Line | v | v | v | v | v | v | | 20 | Shape | v | v | v | v | v | v | +| 21 | Chart | v | - | - | - | - | - | Legend: @@ -737,6 +741,10 @@ To be completed. To be completed. +## Charts + +To be completed. + # Styles ## Section diff --git a/samples/Sample_32_Chart.php b/samples/Sample_32_Chart.php new file mode 100644 index 00000000..26d6c420 --- /dev/null +++ b/samples/Sample_32_Chart.php @@ -0,0 +1,36 @@ +addSection(array('colsNum' => 2)); +$phpWord->addTitleStyle(1, array('size' => 14, 'bold' => true), array('keepNext' => true, 'spaceBefore' => 240)); + +$chartTypes = array('pie', 'doughnut', 'bar', 'line', 'area', 'scatter', 'radar'); +$twoSeries = array('bar', 'line', 'area', 'scatter', 'radar'); +$threeSeries = array('bar', 'line'); +$categories = array('A', 'B', 'C', 'D', 'E'); +$series1 = array(1, 3, 2, 5, 4); +$series2 = array(3, 1, 7, 2, 6); +$series3 = array(8, 3, 2, 5, 4); + +foreach ($chartTypes as $chartType) { + $section->addTitle(ucfirst($chartType), 1); + $chart = $section->addChart($chartType, $categories, $series1); + if (in_array($chartType, $twoSeries)) { + $chart->addSeries($categories, $series2); + } + if (in_array($chartType, $threeSeries)) { + $chart->addSeries($categories, $series3); + } + $section->addTextBreak(); +} + +// Save file +echo write($phpWord, basename(__FILE__, '.php'), $writers); +if (!CLI) { + include_once 'Sample_Footer.php'; +} diff --git a/src/PhpWord/Collection/Charts.php b/src/PhpWord/Collection/Charts.php new file mode 100644 index 00000000..cfccee2e --- /dev/null +++ b/src/PhpWord/Collection/Charts.php @@ -0,0 +1,27 @@ + array('Section'), 'TOC' => array('Section'), 'PageBreak' => array('Section'), + 'Chart' => array('Section'), ); // Special condition, e.g. preservetext can only exists in cell when // the cell is located in header or footer diff --git a/src/PhpWord/Element/AbstractElement.php b/src/PhpWord/Element/AbstractElement.php index fe133fdd..3fd2e4d0 100644 --- a/src/PhpWord/Element/AbstractElement.php +++ b/src/PhpWord/Element/AbstractElement.php @@ -109,7 +109,7 @@ abstract class AbstractElement protected $mediaRelation = false; /** - * Is part of collection; true for Title, Footnote, and Endnote + * Is part of collection; true for Title, Footnote, Endnote, and Chart * * @var bool */ diff --git a/src/PhpWord/Element/Chart.php b/src/PhpWord/Element/Chart.php new file mode 100644 index 00000000..24f2bb78 --- /dev/null +++ b/src/PhpWord/Element/Chart.php @@ -0,0 +1,102 @@ +setType($type); + $this->addSeries($categories, $values); + } + + /** + * Get type + * + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * Set type + * + * @param string $value + */ + public function setType($value) + { + $enum = array('pie', 'doughnut', 'line', 'bar', 'area', 'radar', 'scatter'); + $this->type = $this->setEnumVal($value, $enum, 'pie'); + } + + /** + * Add series + * + * @param array $categories + * @param array $values + */ + public function addSeries($categories, $values) + { + $this->series[] = array('categories' => $categories, 'values' => $values); + } + + /** + * Get series + * + * @return array + */ + public function getSeries() + { + return $this->series; + } +} diff --git a/src/PhpWord/Element/Footnote.php b/src/PhpWord/Element/Footnote.php index e263933c..162a703e 100644 --- a/src/PhpWord/Element/Footnote.php +++ b/src/PhpWord/Element/Footnote.php @@ -37,7 +37,7 @@ class Footnote extends AbstractContainer protected $paragraphStyle; /** - * Is part of collection; true for Title, Footnote, and Endnote + * Is part of collection * * @var bool */ diff --git a/src/PhpWord/Element/Title.php b/src/PhpWord/Element/Title.php index a4faeb70..8d385845 100644 --- a/src/PhpWord/Element/Title.php +++ b/src/PhpWord/Element/Title.php @@ -47,7 +47,7 @@ class Title extends AbstractElement private $style; /** - * Is part of collection; true for Title, Footnote, and Endnote + * Is part of collection * * @var bool */ diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index de9d8433..d4c8df9c 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -26,9 +26,11 @@ use PhpOffice\PhpWord\Exception\Exception; * @method Collection\Titles getTitles() * @method Collection\Footnotes getFootnotes() * @method Collection\Endnotes getEndnotes() + * @method Collection\Charts getCharts() * @method int addTitle(Element\Title $title) * @method int addFootnote(Element\Footnote $footnote) * @method int addEndnote(Element\Endnote $endnote) + * @method int addChart(Element\Chart $chart) * * @method Style\Paragraph addParagraphStyle(string $styleName, array $styles) * @method Style\Font addFontStyle(string $styleName, mixed $fontStyle, mixed $paragraphStyle = null) @@ -80,7 +82,7 @@ class PhpWord { $this->documentProperties = new DocumentProperties(); - $collections = array('Titles', 'Footnotes', 'Endnotes'); + $collections = array('Titles', 'Footnotes', 'Endnotes', 'Charts'); foreach ($collections as $collection) { $class = 'PhpOffice\\PhpWord\\Collection\\' . $collection; $this->collections[$collection] = new $class(); @@ -108,7 +110,7 @@ class PhpWord $addCollection = array(); $addStyle = array(); - $collections = array('Title', 'Footnote', 'Endnote'); + $collections = array('Title', 'Footnote', 'Endnote', 'Chart'); foreach ($collections as $collection) { $getCollection[] = strtolower("get{$collection}s"); $addCollection[] = strtolower("add{$collection}"); diff --git a/src/PhpWord/Shared/XMLWriter.php b/src/PhpWord/Shared/XMLWriter.php index cb00c70b..8691ae1d 100644 --- a/src/PhpWord/Shared/XMLWriter.php +++ b/src/PhpWord/Shared/XMLWriter.php @@ -139,6 +139,29 @@ class XMLWriter } } + /** + * Write simple element and attribute(s) block + * + * There are two options: + * 1. If the `$attributes` is an array, then it's an associative array of attributes + * 2. If not, then it's a simple attribute-value pair + * + * @param string $element + * @param string|array $attributes + * @param string $value + */ + public function writeElementBlock($element, $attributes, $value = null) + { + $this->xmlWriter->startElement($element); + if (!is_array($attributes)) { + $attributes = array($attributes => $value); + } + foreach ($attributes as $attribute => $value) { + $this->xmlWriter->writeAttribute($attribute, $value); + } + $this->xmlWriter->endElement(); + } + /** * Write element if ... * diff --git a/src/PhpWord/Writer/Word2007.php b/src/PhpWord/Writer/Word2007.php index 751b58b6..d15f40ac 100644 --- a/src/PhpWord/Writer/Word2007.php +++ b/src/PhpWord/Writer/Word2007.php @@ -71,6 +71,7 @@ class Word2007 extends AbstractWriter implements WriterInterface 'Footer' => '', 'Footnotes' => '', 'Endnotes' => '', + 'Chart' => '', ); foreach (array_keys($this->parts) as $partName) { $partClass = get_class($this) . '\\Part\\' . $partName; @@ -127,6 +128,7 @@ class Word2007 extends AbstractWriter implements WriterInterface $this->addNotes($zip, $rId, 'footnote'); $this->addNotes($zip, $rId, 'endnote'); + $this->addChart($zip, $rId); // Write parts foreach ($this->parts as $partName => $fileName) { @@ -249,6 +251,40 @@ class Word2007 extends AbstractWriter implements WriterInterface } } + /** + * Add chart + * + * @param \PhpOffice\PhpWord\Shared\ZipArchive $zip + * @param integer $rId + */ + private function addChart(ZipArchive $zip, &$rId) + { + $phpWord = $this->getPhpWord(); + + $collection = $phpWord->getCharts(); + $index = 0; + if ($collection->countItems() > 0) { + foreach ($collection->getItems() as $chart) { + $index++; + $rId++; + $filename = "charts/chart{$index}.xml"; + + // ContentTypes.xml + $this->contentTypes['override']["/word/{$filename}"] = 'chart'; + + // word/_rels/document.xml.rel + $this->relationships[] = array('target' => $filename, 'type' => 'chart', 'rID' => $rId); + + // word/charts/chartN.xml + /** @var \PhpOffice\PhpWord\Element\Chart $chart */ + $chart->setRelationId($rId); + $writerPart = $this->getWriterPart('Chart'); + $writerPart->setElement($chart); + $zip->addFromString("word/{$filename}", $writerPart->write()); + } + } + } + /** * Register content types for each media * diff --git a/src/PhpWord/Writer/Word2007/Element/Chart.php b/src/PhpWord/Writer/Word2007/Element/Chart.php new file mode 100644 index 00000000..4330e2fe --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/Chart.php @@ -0,0 +1,74 @@ +getXmlWriter(); + $element = $this->getElement(); + if (!$element instanceof ChartElement) { + return; + } + + $rId = $element->getRelationId(); + + if (!$this->withoutP) { + $xmlWriter->startElement('w:p'); + } + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:drawing'); + $xmlWriter->startElement('wp:inline'); + + // EMU + $xmlWriter->writeElementBlock('wp:extent', array('cx' => '2000000', 'cy' => '2000000')); + $xmlWriter->writeElementBlock('wp:docPr', array('id' => $rId, 'name' => "Chart{$rId}")); + + $xmlWriter->startElement('a:graphic'); + $xmlWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); + $xmlWriter->startElement('a:graphicData'); + $xmlWriter->writeAttribute('uri', 'http://schemas.openxmlformats.org/drawingml/2006/chart'); + + $xmlWriter->startElement('c:chart'); + $xmlWriter->writeAttribute('r:id', "rId{$rId}"); + $xmlWriter->writeAttribute('xmlns:c', 'http://schemas.openxmlformats.org/drawingml/2006/chart'); + $xmlWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + $xmlWriter->endElement(); // c:chart + + $xmlWriter->endElement(); // a:graphicData + $xmlWriter->endElement(); // a:graphic + + $xmlWriter->endElement(); // wp:inline + $xmlWriter->endElement(); // w:drawing + $xmlWriter->endElement(); // w:r + + $this->endElementP(); // w:p + } +} diff --git a/src/PhpWord/Writer/Word2007/Part/Chart.php b/src/PhpWord/Writer/Word2007/Part/Chart.php new file mode 100644 index 00000000..66e43914 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -0,0 +1,304 @@ + array('type' => 'pieChart', 'colors' => 1), + 'doughnut' => array('type' => 'doughnutChart', 'colors' => 1, 'hole' => 75), + 'bar' => array('type' => 'barChart', 'colors' => 0, 'axes' => true, 'bar' => 'col'), + 'line' => array('type' => 'lineChart', 'colors' => 0, 'axes' => true), + 'area' => array('type' => 'areaChart', 'colors' => 0, 'axes' => true), + 'radar' => array('type' => 'radarChart', 'colors' => 0, 'axes' => true, 'radar' => 'standard'), + 'scatter' => array('type' => 'scatterChart', 'colors' => 0, 'axes' => true, 'scatter' => 'marker'), + ); + + /** + * Chart options + * + * @var array + */ + private $options = array(); + + /** + * Set chart element + */ + public function setElement(ChartElement $element) + { + $this->element = $element; + } + + /** + * Write part + * + * @return string + */ + public function write() + { + $xmlWriter = $this->getXmlWriter(); + + $xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); + $xmlWriter->startElement('c:chartSpace'); + $xmlWriter->writeAttribute('xmlns:c', 'http://schemas.openxmlformats.org/drawingml/2006/chart'); + $xmlWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); + $xmlWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + + $this->writeChart($xmlWriter); + $this->writeShape($xmlWriter); + + $xmlWriter->endElement(); // c:chartSpace + + return $xmlWriter->getData(); + } + + /** + * Write chart + * + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_Chart.html + */ + private function writeChart(XMLWriter $xmlWriter) + { + $xmlWriter->startElement('c:chart'); + + $xmlWriter->writeElementBlock('c:autoTitleDeleted', 'val', 1); + + $this->writePlotArea($xmlWriter); + + $xmlWriter->endElement(); // c:chart + } + + /** + * Write plot area + * + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_PlotArea.html + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_PieChart.html + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_DoughnutChart.html + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_BarChart.html + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_LineChart.html + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_AreaChart.html + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_RadarChart.html + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_ScatterChart.html + */ + private function writePlotArea(XMLWriter $xmlWriter) + { + $type = $this->element->getType(); + $this->options = $this->types[$type]; + + $xmlWriter->startElement('c:plotArea'); + $xmlWriter->writeElement('c:layout'); + + // Chart + $xmlWriter->startElement('c:' . $this->options['type']); + + $xmlWriter->writeElementBlock('c:varyColors', 'val', $this->options['colors']); + if ($type == 'area') { + $xmlWriter->writeElementBlock('c:grouping', 'val', 'standard'); + } + if (isset($this->options['hole'])) { + $xmlWriter->writeElementBlock('c:holeSize', 'val', $this->options['hole']); + } + if (isset($this->options['bar'])) { + $xmlWriter->writeElementBlock('c:barDir', 'val', $this->options['bar']); // bar|col + $xmlWriter->writeElementBlock('c:grouping', 'val', 'clustered'); + } + if (isset($this->options['radar'])) { + $xmlWriter->writeElementBlock('c:radarStyle', 'val', $this->options['radar']); + } + if (isset($this->options['scatter'])) { + $xmlWriter->writeElementBlock('c:scatterStyle', 'val', $this->options['scatter']); + } + + // Series + $this->writeSeries($xmlWriter, isset($this->options['scatter'])); + + // Axes + if (isset($this->options['axes'])) { + $xmlWriter->writeElementBlock('c:axId', 'val', 1); + $xmlWriter->writeElementBlock('c:axId', 'val', 2); + } + + $xmlWriter->endElement(); // chart type + + // Axes + if (isset($this->options['axes'])) { + $this->writeAxis($xmlWriter, 'cat'); + $this->writeAxis($xmlWriter, 'val'); + } + + $xmlWriter->endElement(); // c:plotArea + } + + /** + * Write series + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param bool $scatter + */ + private function writeSeries(XMLWriter $xmlWriter, $scatter = false) + { + $series = $this->element->getSeries(); + + $index = 0; + foreach ($series as $seriesItem) { + $categories = $seriesItem['categories']; + $values = $seriesItem['values']; + + $xmlWriter->startElement('c:ser'); + + $xmlWriter->writeElementBlock('c:idx', 'val', $index); + $xmlWriter->writeElementBlock('c:order', 'val', $index); + + if (isset($this->options['scatter'])) { + $this->writeShape($xmlWriter); + } + + if ($scatter === true) { + $this->writeSeriesItem($xmlWriter, 'xVal', $categories); + $this->writeSeriesItem($xmlWriter, 'yVal', $values); + } else { + $this->writeSeriesItem($xmlWriter, 'cat', $categories); + $this->writeSeriesItem($xmlWriter, 'val', $values); + } + + $xmlWriter->endElement(); // c:ser + $index++; + } + + } + + /** + * Write series items + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param string $type + * @param array $values + */ + private function writeSeriesItem(XMLWriter $xmlWriter, $type, $values) + { + $types = array( + 'cat' => array('c:cat', 'c:strLit'), + 'val' => array('c:val', 'c:numLit'), + 'xVal' => array('c:xVal', 'c:strLit'), + 'yVal' => array('c:yVal', 'c:numLit'), + ); + list($itemType, $itemLit) = $types[$type]; + + $xmlWriter->startElement($itemType); + $xmlWriter->startElement($itemLit); + + $index = 0; + foreach ($values as $value) { + $xmlWriter->startElement('c:pt'); + $xmlWriter->writeAttribute('idx', $index); + + $xmlWriter->startElement('c:v'); + $xmlWriter->writeRaw($value); + $xmlWriter->endElement(); // c:v + + $xmlWriter->endElement(); // c:pt + $index++; + } + + $xmlWriter->endElement(); // $itemLit + $xmlWriter->endElement(); // $itemType + } + + /** + * Write axis + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param string $type + * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_CatAx.html + */ + private function writeAxis(XMLWriter $xmlWriter, $type) + { + $types = array( + 'cat' => array('c:catAx', 1, 'b', 2), + 'val' => array('c:valAx', 2, 'l', 1), + ); + list($axisType, $axisId, $axisPos, $axisCross) = $types[$type]; + + $xmlWriter->startElement($axisType); + + $xmlWriter->writeElementBlock('c:axId', 'val', $axisId); + $xmlWriter->writeElementBlock('c:axPos', 'val', $axisPos); + $xmlWriter->writeElementBlock('c:crossAx', 'val', $axisCross); + $xmlWriter->writeElementBlock('c:auto', 'val', 1); + + if (isset($this->options['axes'])) { + $xmlWriter->writeElementBlock('c:delete', 'val', 0); + $xmlWriter->writeElementBlock('c:majorTickMark', 'val', 'none'); + $xmlWriter->writeElementBlock('c:minorTickMark', 'val', 'none'); + $xmlWriter->writeElementBlock('c:tickLblPos', 'val', 'none'); // nextTo + $xmlWriter->writeElementBlock('c:crosses', 'val', 'autoZero'); + } + if (isset($this->options['radar'])) { + $xmlWriter->writeElement('c:majorGridlines'); + } + + $xmlWriter->startElement('c:scaling'); + $xmlWriter->writeElementBlock('c:orientation', 'val', 'minMax'); + $xmlWriter->endElement(); // c:scaling + + $this->writeShape($xmlWriter, true); + + $xmlWriter->endElement(); // $axisType + } + + /** + * Write shape + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param bool $line + * @link http://www.datypic.com/sc/ooxml/t-a_CT_ShapeProperties.html + */ + private function writeShape(XMLWriter $xmlWriter, $line = false) + { + $xmlWriter->startElement('c:spPr'); + $xmlWriter->startElement('a:ln'); + if ($line === true) { + $xmlWriter->writeElement('a:solidFill'); + } else { + $xmlWriter->writeElement('a:noFill'); + } + $xmlWriter->endElement(); // a:ln + $xmlWriter->endElement(); // c:spPr + } +} diff --git a/src/PhpWord/Writer/Word2007/Part/ContentTypes.php b/src/PhpWord/Writer/Word2007/Part/ContentTypes.php index b6f23f47..ac636d3a 100644 --- a/src/PhpWord/Writer/Word2007/Part/ContentTypes.php +++ b/src/PhpWord/Writer/Word2007/Part/ContentTypes.php @@ -37,6 +37,7 @@ class ContentTypes extends AbstractPart $openXMLPrefix = 'application/vnd.openxmlformats-'; $wordMLPrefix = $openXMLPrefix . 'officedocument.wordprocessingml.'; + $drawingMLPrefix = $openXMLPrefix . 'officedocument.drawingml.'; $overrides = array( '/docProps/core.xml' => $openXMLPrefix . 'package.core-properties+xml', '/docProps/app.xml' => $openXMLPrefix . 'officedocument.extended-properties+xml', @@ -53,7 +54,11 @@ class ContentTypes extends AbstractPart $defaults = $contentTypes['default']; if (!empty($contentTypes['override'])) { foreach ($contentTypes['override'] as $key => $val) { - $overrides[$key] = $wordMLPrefix . $val . '+xml'; + if ($val == 'chart') { + $overrides[$key] = $drawingMLPrefix . $val . '+xml'; + } else { + $overrides[$key] = $wordMLPrefix . $val . '+xml'; + } } } diff --git a/tests/PhpWord/Tests/Writer/RTFTest.php b/tests/PhpWord/Tests/Writer/RTFTest.php index c1448106..5b983b35 100644 --- a/tests/PhpWord/Tests/Writer/RTFTest.php +++ b/tests/PhpWord/Tests/Writer/RTFTest.php @@ -91,7 +91,7 @@ class RTFTest extends \PHPUnit_Framework_TestCase $this->assertTrue(file_exists($file)); - unlink($file); + @unlink($file); } /** diff --git a/tests/PhpWord/Tests/Writer/Word2007/ElementTest.php b/tests/PhpWord/Tests/Writer/Word2007/ElementTest.php index c774e9f3..0ba29f2f 100644 --- a/tests/PhpWord/Tests/Writer/Word2007/ElementTest.php +++ b/tests/PhpWord/Tests/Writer/Word2007/ElementTest.php @@ -41,7 +41,7 @@ class ElementTest extends \PHPUnit_Framework_TestCase $elements = array( 'CheckBox', 'Container', 'Footnote', 'Image', 'Link', 'ListItem', 'ListItemRun', 'Object', 'PreserveText', 'Table', 'Text', 'TextBox', 'TextBreak', 'Title', 'TOC', - 'Field', 'Line', 'Shape' + 'Field', 'Line', 'Shape', 'Chart' ); foreach ($elements as $element) { $objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element\\' . $element; @@ -148,4 +148,30 @@ class ElementTest extends \PHPUnit_Framework_TestCase $this->assertTrue($doc->elementExists($path)); } } + + /** + * Test shape elements + */ + public function testChartElement() + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + + $chartTypes = array('pie', 'doughnut', 'bar', 'line', 'area', 'scatter', 'radar'); + $categories = array('A', 'B', 'C', 'D', 'E'); + $series1 = array(1, 3, 2, 5, 4); + foreach ($chartTypes as $chartType) { + $section->addChart($chartType, $categories, $series1); + } + + $doc = TestHelperDOCX::getDocument($phpWord); + + $index = 0; + foreach ($chartTypes as $chartType) { + $index++; + $file = "word/charts/chart{$index}.xml"; + $path = "/c:chartSpace/c:chart/c:plotArea/c:{$chartType}Chart"; + $this->assertTrue($doc->elementExists($path, $file)); + } + } }