diff --git a/CHANGELOG.md b/CHANGELOG.md index 52bd6aac68..f963a3cd46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,8 +14,8 @@ This is the last version to support PHP 5.3 - Introduced the `\PhpOffice\PhpWord\SimpleType\NumberFormat` simple type. - @troosan - Support for ContextualSpacing - @postHawk #1088 - Possiblity to hide spelling and/or grammatical errors - @troosan #542 +- Possiblity to set default document language as well as changing the language for each text element - @troosan #1108 - Support for Comments - @troosan #1067 -- Add support for changing the document language - @troosan #1108 ### Fixed - Loosen dependency to Zend diff --git a/docs/general.rst b/docs/general.rst index 87fecb77a4..5b5c5d9ee2 100644 --- a/docs/general.rst +++ b/docs/general.rst @@ -201,6 +201,25 @@ The default symbol to represent a decimal figure is the ``.`` in english. In fre $phpWord->getSettings()->setDecimalSymbol(','); +Document Language +~~~~~~~~~~~~~~~~~ +The default language of the document can be change with the following. + +.. code-block:: php + + $phpWord->getSettings()->setThemeFontLang(new Language(Language::FR_BE)); + +``Languge`` has 3 parameters, one for Latin languages, one for East Asian languages and one for Complex (Bi-Directional) languages. +A couple of language codes are provided in the ``PhpOffice\PhpWord\ComplexType\Language`` class but any valid code/ID can be used. + +In case you are generating an RTF document the Language need to be set differently. + +.. code-block:: php + + $lang = new Language(); + $lang->setLangId(Language::EN_GB_ID); + $phpWord->getSettings()->setThemeFontLang($lang); + Document information -------------------- diff --git a/docs/styles.rst b/docs/styles.rst index 4f8a53fede..e8d2aec8a7 100644 --- a/docs/styles.rst +++ b/docs/styles.rst @@ -55,6 +55,8 @@ Available Font style options: - ``subScript``. Subscript, *true* or *false*. - ``superScript``. Superscript, *true* or *false*. - ``underline``. Underline, *dash*, *dotted*, etc. +- ``lang``. Language, either a language code like *en-US*, *fr-BE*, etc. or an object (or as an array) if you need to set eastAsian or bidirectional languages + See ``\PhpOffice\PhpWord\Style\Language`` class for some language codes. .. _paragraph-style: @@ -64,7 +66,7 @@ Paragraph Available Paragraph style options: - ``alignment``. Supports all alignment modes since 1st Edition of ECMA-376 standard up till ISO/IEC 29500:2012. -See ``\PhpOffice\PhpWord\SimpleType\Jc`` class for the details. + See ``\PhpOffice\PhpWord\SimpleType\Jc`` class for the details. - ``basedOn``. Parent style. - ``hanging``. Hanging by how much. - ``indent``. Indent by how much. @@ -87,7 +89,7 @@ Table Available Table style options: - ``alignment``. Supports all alignment modes since 1st Edition of ECMA-376 standard up till ISO/IEC 29500:2012. -See ``\PhpOffice\PhpWord\SimpleType\JcTable`` and ``\PhpOffice\PhpWord\SimpleType\Jc`` classes for the details. + See ``\PhpOffice\PhpWord\SimpleType\JcTable`` and ``\PhpOffice\PhpWord\SimpleType\Jc`` classes for the details. - ``bgColor``. Background color, e.g. '9966CC'. - ``border(Top|Right|Bottom|Left)Color``. Border color, e.g. '9966CC'. - ``border(Top|Right|Bottom|Left)Size``. Border size in twips. @@ -106,7 +108,8 @@ Available Cell style options: - ``border(Top|Right|Bottom|Left)Color``. Border color, e.g. '9966CC'. - ``border(Top|Right|Bottom|Left)Size``. Border size in twips. - ``gridSpan``. Number of columns spanned. -- ``textDirection(btLr|tbRl)``. Direction of text. You can use constants ``\PhpOffice\PhpWord\Style\Cell::TEXT_DIR_BTLR`` and ``\PhpOffice\PhpWord\Style\Cell::TEXT_DIR_TBRL`` +- ``textDirection(btLr|tbRl)``. Direction of text. + You can use constants ``\PhpOffice\PhpWord\Style\Cell::TEXT_DIR_BTLR`` and ``\PhpOffice\PhpWord\Style\Cell::TEXT_DIR_TBRL`` - ``valign``. Vertical alignment, *top*, *center*, *both*, *bottom*. - ``vMerge``. *restart* or *continue*. - ``width``. Cell width in twips. @@ -133,7 +136,7 @@ Numbering level Available NumberingLevel style options: - ``alignment``. Supports all alignment modes since 1st Edition of ECMA-376 standard up till ISO/IEC 29500:2012. -See ``\PhpOffice\PhpWord\SimpleType\Jc`` class for the details. + See ``\PhpOffice\PhpWord\SimpleType\Jc`` class for the details. - ``font``. Font name. - ``format``. Numbering format bullet\|decimal\|upperRoman\|lowerRoman\|upperLetter\|lowerLetter. - ``hanging``. See paragraph style. diff --git a/samples/Sample_01_SimpleText.php b/samples/Sample_01_SimpleText.php index 1e51b2c072..fae6c21031 100644 --- a/samples/Sample_01_SimpleText.php +++ b/samples/Sample_01_SimpleText.php @@ -1,9 +1,16 @@ getSettings()->setThemeFontLang($languageEnGb); $fontStyleName = 'rStyle'; $phpWord->addFontStyle($fontStyleName, array('bold' => true, 'italic' => true, 'size' => 16, 'allCaps' => true, 'doubleStrikethrough' => true)); @@ -20,6 +27,10 @@ $section->addTitle('Welcome to PhpWord', 1); $section->addText('Hello World!'); +// $pStyle = new Font(); +// $pStyle->setLang() +$section->addText('Ce texte-ci est en français.', array('lang' => \PhpOffice\PhpWord\Style\Language::FR_BE)); + // Two text break $section->addTextBreak(2); diff --git a/samples/Sample_10_EastAsianFontStyle.php b/samples/Sample_10_EastAsianFontStyle.php index 2541af86dc..87345ae0e8 100644 --- a/samples/Sample_10_EastAsianFontStyle.php +++ b/samples/Sample_10_EastAsianFontStyle.php @@ -7,7 +7,7 @@ $section = $phpWord->addSection(); $header = array('size' => 16, 'bold' => true); //1.Use EastAisa FontStyle -$section->addText('中文楷体样式测试', array('name' => '楷体', 'size' => 16, 'color' => '1B2232')); +$section->addText('中文楷体样式测试', array('name' => '楷体', 'size' => 16, 'color' => '1B2232', 'lang' => array('latin' => 'en-US', 'eastAsia' => 'zh-CN'))); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/src/PhpWord/ComplexType/TrackChangesView.php b/src/PhpWord/ComplexType/TrackChangesView.php index ea26bc3c3b..9c8948ae1d 100644 --- a/src/PhpWord/ComplexType/TrackChangesView.php +++ b/src/PhpWord/ComplexType/TrackChangesView.php @@ -135,10 +135,10 @@ public function hasFormatting() /** * Set Display Formatting Revisions * - * @param boolean $insDel + * @param boolean|null $formatting * Set to true to show formatting revisions */ - public function setFormatting($formatting) + public function setFormatting($formatting = null) { $this->formatting = $formatting === null ? true : $formatting; } diff --git a/src/PhpWord/Element/AbstractElement.php b/src/PhpWord/Element/AbstractElement.php index f657dd1b61..4ff4978a7b 100644 --- a/src/PhpWord/Element/AbstractElement.php +++ b/src/PhpWord/Element/AbstractElement.php @@ -231,7 +231,7 @@ public function setElementIndex($value) /** * Get element unique ID * - * @return string + * @return integer */ public function getElementId() { diff --git a/src/PhpWord/Element/Bookmark.php b/src/PhpWord/Element/Bookmark.php index c865893fad..4df06afb4e 100644 --- a/src/PhpWord/Element/Bookmark.php +++ b/src/PhpWord/Element/Bookmark.php @@ -45,9 +45,7 @@ class Bookmark extends AbstractElement */ public function __construct($name) { - $this->name = CommonText::toUTF8($name); - return $this; } /** diff --git a/src/PhpWord/Element/CheckBox.php b/src/PhpWord/Element/CheckBox.php index 3fc578ef37..b049c7f1bf 100644 --- a/src/PhpWord/Element/CheckBox.php +++ b/src/PhpWord/Element/CheckBox.php @@ -40,7 +40,6 @@ class CheckBox extends Text * @param string $text * @param mixed $fontStyle * @param mixed $paragraphStyle - * @return self */ public function __construct($name = null, $text = null, $fontStyle = null, $paragraphStyle = null) { diff --git a/src/PhpWord/Element/Comment.php b/src/PhpWord/Element/Comment.php index 685ed2964b..5e0ebe630d 100644 --- a/src/PhpWord/Element/Comment.php +++ b/src/PhpWord/Element/Comment.php @@ -61,7 +61,6 @@ public function __construct($author, $date, $initials) { parent::__construct($author, $date); $this->initials = $initials; - return $this; } /** diff --git a/src/PhpWord/Element/FormField.php b/src/PhpWord/Element/FormField.php index c7cb44d240..414714a8d4 100644 --- a/src/PhpWord/Element/FormField.php +++ b/src/PhpWord/Element/FormField.php @@ -35,7 +35,7 @@ class FormField extends Text /** * Form field name * - * @var string + * @var string|bool|int */ private $name; @@ -70,7 +70,6 @@ class FormField extends Text * @param string $type * @param mixed $fontStyle * @param mixed $paragraphStyle - * @return self */ public function __construct($type, $fontStyle = null, $paragraphStyle = null) { diff --git a/src/PhpWord/Element/Link.php b/src/PhpWord/Element/Link.php index 4a72e167f0..6641b46d5b 100644 --- a/src/PhpWord/Element/Link.php +++ b/src/PhpWord/Element/Link.php @@ -83,7 +83,6 @@ public function __construct($source, $text = null, $fontStyle = null, $paragraph $this->fontStyle = $this->setNewStyle(new Font('text'), $fontStyle); $this->paragraphStyle = $this->setNewStyle(new Paragraph(), $paragraphStyle); $this->internal = $internal; - return $this; } /** diff --git a/src/PhpWord/Element/PreserveText.php b/src/PhpWord/Element/PreserveText.php index 65e17e35b5..813c13960d 100644 --- a/src/PhpWord/Element/PreserveText.php +++ b/src/PhpWord/Element/PreserveText.php @@ -54,7 +54,6 @@ class PreserveText extends AbstractElement * @param string $text * @param mixed $fontStyle * @param mixed $paragraphStyle - * @return self */ public function __construct($text = null, $fontStyle = null, $paragraphStyle = null) { diff --git a/src/PhpWord/Element/SDT.php b/src/PhpWord/Element/SDT.php index 58a477d92b..b0c68b0f85 100644 --- a/src/PhpWord/Element/SDT.php +++ b/src/PhpWord/Element/SDT.php @@ -51,7 +51,6 @@ class SDT extends Text * @param string $type * @param mixed $fontStyle * @param mixed $paragraphStyle - * @return self */ public function __construct($type, $fontStyle = null, $paragraphStyle = null) { diff --git a/src/PhpWord/Element/TOC.php b/src/PhpWord/Element/TOC.php index 54ae384433..d3ab2be146 100644 --- a/src/PhpWord/Element/TOC.php +++ b/src/PhpWord/Element/TOC.php @@ -36,7 +36,7 @@ class TOC extends AbstractElement /** * Font style * - * @var \PhpOffice\PhpWord\Style\Font|array|string + * @var \PhpOffice\PhpWord\Style\Font|string */ private $fontStyle; @@ -121,7 +121,7 @@ public function getStyleTOC() /** * Get Font Style * - * @return \PhpOffice\PhpWord\Style\Font + * @return \PhpOffice\PhpWord\Style\Font|string */ public function getStyleFont() { diff --git a/src/PhpWord/Element/TrackChange.php b/src/PhpWord/Element/TrackChange.php index 782e6f3550..1df7148db6 100644 --- a/src/PhpWord/Element/TrackChange.php +++ b/src/PhpWord/Element/TrackChange.php @@ -45,7 +45,7 @@ class TrackChange extends AbstractContainer * Create a new TrackChange Element * * @param string $author - * @param DateTime $date + * @param \DateTime $date */ public function __construct($author, \DateTime $date) { diff --git a/src/PhpWord/Metadata/Settings.php b/src/PhpWord/Metadata/Settings.php index cd0eaabe2b..64788cc3b7 100644 --- a/src/PhpWord/Metadata/Settings.php +++ b/src/PhpWord/Metadata/Settings.php @@ -19,6 +19,7 @@ use PhpOffice\PhpWord\ComplexType\ProofState; use PhpOffice\PhpWord\SimpleType\Zoom; use PhpOffice\PhpWord\ComplexType\TrackChangesView; +use PhpOffice\PhpWord\Style\Language; /** * Setting class @@ -100,6 +101,13 @@ class Settings */ private $evenAndOddHeaders = false; + /** + * Theme Font Languages + * + * @var Language + */ + private $themeFontLang; + /** * Radix Point for Field Code Evaluation * @@ -291,6 +299,26 @@ public function setZoom($zoom) } } + /** + * Returns the Language + * + * @return Language + */ + public function getThemeFontLang() + { + return $this->themeFontLang; + } + + /** + * sets the Language for this document + * + * @param Language $themeFontLang + */ + public function setThemeFontLang($themeFontLang) + { + $this->themeFontLang = $themeFontLang; + } + /** * Returns the Radix Point for Field Code Evaluation * diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 5aafcb0d24..c94a3546a8 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -314,18 +314,20 @@ protected function readParagraphStyle(XMLReader $xmlReader, \DOMElement $domNode $styleNode = $xmlReader->getElement('w:pPr', $domNode); $styleDefs = array( - 'styleName' => array(self::READ_VALUE, 'w:pStyle'), - 'alignment' => array(self::READ_VALUE, 'w:jc'), - 'basedOn' => array(self::READ_VALUE, 'w:basedOn'), - 'next' => array(self::READ_VALUE, 'w:next'), - 'indent' => array(self::READ_VALUE, 'w:ind', 'w:left'), - 'hanging' => array(self::READ_VALUE, 'w:ind', 'w:hanging'), - 'spaceAfter' => array(self::READ_VALUE, 'w:spacing', 'w:after'), - 'spaceBefore' => array(self::READ_VALUE, 'w:spacing', 'w:before'), - 'widowControl' => array(self::READ_FALSE, 'w:widowControl'), - 'keepNext' => array(self::READ_TRUE, 'w:keepNext'), - 'keepLines' => array(self::READ_TRUE, 'w:keepLines'), - 'pageBreakBefore' => array(self::READ_TRUE, 'w:pageBreakBefore'), + 'styleName' => array(self::READ_VALUE, 'w:pStyle'), + 'alignment' => array(self::READ_VALUE, 'w:jc'), + 'basedOn' => array(self::READ_VALUE, 'w:basedOn'), + 'next' => array(self::READ_VALUE, 'w:next'), + 'indent' => array(self::READ_VALUE, 'w:ind', 'w:left'), + 'hanging' => array(self::READ_VALUE, 'w:ind', 'w:hanging'), + 'spaceAfter' => array(self::READ_VALUE, 'w:spacing', 'w:after'), + 'spaceBefore' => array(self::READ_VALUE, 'w:spacing', 'w:before'), + 'widowControl' => array(self::READ_FALSE, 'w:widowControl'), + 'keepNext' => array(self::READ_TRUE, 'w:keepNext'), + 'keepLines' => array(self::READ_TRUE, 'w:keepLines'), + 'pageBreakBefore' => array(self::READ_TRUE, 'w:pageBreakBefore'), + 'contextualSpacing' => array(self::READ_TRUE, 'w:contextualSpacing'), + 'bidi' => array(self::READ_TRUE, 'w:bidi'), ); return $this->readStyleDefs($xmlReader, $styleNode, $styleDefs); @@ -369,6 +371,9 @@ protected function readFontStyle(XMLReader $xmlReader, \DOMElement $domNode) 'subScript' => array(self::READ_EQUAL, 'w:vertAlign', 'w:val', 'subscript'), 'fgColor' => array(self::READ_VALUE, 'w:highlight'), 'rtl' => array(self::READ_TRUE, 'w:rtl'), + 'font-latin' => array(self::READ_VALUE, 'w:font', 'w:val'), + 'font-eastAsia' => array(self::READ_VALUE, 'w:font', 'w:eastAsia'), + 'font-bidi' => array(self::READ_VALUE, 'w:font', 'w:bidi'), ); return $this->readStyleDefs($xmlReader, $styleNode, $styleDefs); diff --git a/src/PhpWord/Reader/Word2007/Settings.php b/src/PhpWord/Reader/Word2007/Settings.php index 7ade4dc5b1..581d6b3d4a 100644 --- a/src/PhpWord/Reader/Word2007/Settings.php +++ b/src/PhpWord/Reader/Word2007/Settings.php @@ -18,8 +18,9 @@ namespace PhpOffice\PhpWord\Reader\Word2007; use PhpOffice\Common\XMLReader; -use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\ComplexType\TrackChangesView; +use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Style\Language; /** * Settings reader @@ -66,6 +67,28 @@ public function read(PhpWord $phpWord) } } + /** + * Sets the document Language + * + * @param XMLReader $xmlReader + * @param PhpWord $phpWord + * @param \DOMNode $node + */ + protected function setThemeFontLang(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) + { + + $val = $xmlReader->getAttribute('w:val', $node); + $eastAsia = $xmlReader->getAttribute('w:eastAsia', $node); + $bidi = $xmlReader->getAttribute('w:bidi', $node); + + $themeFontLang = new Language(); + $themeFontLang->setLatin($val); + $themeFontLang->setLatin($eastAsia); + $themeFontLang->setLatin($bidi); + + $phpWord->getSettings()->setThemeFontLang($themeFontLang); + } + /** * Sets the document protection * @@ -73,7 +96,7 @@ public function read(PhpWord $phpWord) * @param PhpWord $phpWord * @param \DOMNode $node */ - protected function setDocumentProtection(XMLReader $xmlReader, PhpWord $phpWord, \DOMNode $node) + protected function setDocumentProtection(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) { $documentProtection = $phpWord->getSettings()->getDocumentProtection(); @@ -88,17 +111,17 @@ protected function setDocumentProtection(XMLReader $xmlReader, PhpWord $phpWord, * @param PhpWord $phpWord * @param \DOMNode $node */ - protected function setProofState(XMLReader $xmlReader, PhpWord $phpWord, \DOMNode $node) + protected function setProofState(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) { $proofState = $phpWord->getSettings()->getProofState(); $spelling = $xmlReader->getAttribute('w:spelling', $node); $grammar = $xmlReader->getAttribute('w:grammar', $node); - if ($spelling != null) { + if ($spelling !== null) { $proofState->setSpelling($spelling); } - if ($grammar != null) { + if ($grammar !== null) { $proofState->setGrammar($grammar); } } @@ -110,13 +133,13 @@ protected function setProofState(XMLReader $xmlReader, PhpWord $phpWord, \DOMNod * @param PhpWord $phpWord * @param \DOMNode $node */ - protected function setZoom(XMLReader $xmlReader, PhpWord $phpWord, \DOMNode $node) + protected function setZoom(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) { $percent = $xmlReader->getAttribute('w:percent', $node); $val = $xmlReader->getAttribute('w:val', $node); - if ($percent != null || $val != null) { - $phpWord->getSettings()->setZoom($percent == null ? $val : $percent); + if ($percent !== null || $val !== null) { + $phpWord->getSettings()->setZoom($percent === null ? $val : $percent); } } @@ -127,7 +150,7 @@ protected function setZoom(XMLReader $xmlReader, PhpWord $phpWord, \DOMNode $nod * @param PhpWord $phpWord * @param \DOMNode $node */ - protected function setRevisionView(XMLReader $xmlReader, PhpWord $phpWord, \DOMNode $node) + protected function setRevisionView(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) { $revisionView = new TrackChangesView(); $revisionView->setMarkup($xmlReader->getAttribute('w:markup', $node)); diff --git a/src/PhpWord/Style/AbstractStyle.php b/src/PhpWord/Style/AbstractStyle.php index 05c79ea2da..e2b6dce9e8 100644 --- a/src/PhpWord/Style/AbstractStyle.php +++ b/src/PhpWord/Style/AbstractStyle.php @@ -329,7 +329,7 @@ protected function setObjectVal($value, $styleName, &$style) protected function setPairedVal(&$property, &$pairProperty, $value) { $property = $this->setBoolVal($value, $property); - if ($value == true) { + if ($value === true) { $pairProperty = false; } diff --git a/src/PhpWord/Style/Font.php b/src/PhpWord/Style/Font.php index 5cc80fb323..19f2758d64 100644 --- a/src/PhpWord/Style/Font.php +++ b/src/PhpWord/Style/Font.php @@ -228,6 +228,12 @@ class Font extends AbstractStyle */ private $rtl = false; + /** + * Languages + * @var \PhpOffice\PhpWord\Style\Language + */ + private $lang; + /** * Create new font style * @@ -276,6 +282,7 @@ public function getStyleValues() 'paragraph' => $this->getParagraph(), 'rtl' => $this->isRTL(), 'shading' => $this->getShading(), + 'lang' => $this->getLang(), ); return $styles; @@ -783,6 +790,32 @@ public function setShading($value = null) return $this; } + /** + * Get language + * + * @return \PhpOffice\PhpWord\Style\Language + */ + public function getLang() + { + return $this->lang; + } + + /** + * Set language + * + * @param mixed $value + * @return self + */ + public function setLang($value = null) + { + if (is_string($value) && $value != '') { + $value = new Language($value); + } + $this->setObjectVal($value, 'Language', $this->lang); + + return $this; + } + /** * Get bold * diff --git a/src/PhpWord/Style/Language.php b/src/PhpWord/Style/Language.php new file mode 100644 index 0000000000..4e9220fd44 --- /dev/null +++ b/src/PhpWord/Style/Language.php @@ -0,0 +1,218 @@ +setLatin($latin); + } + if (!empty($eastAsia)) { + $this->setEastAsia($eastAsia); + } + if (!empty($bidirectional)) { + $this->setBidirectional($bidirectional); + } + } + + /** + * Set the Latin Language + * + * @param string $latin + * The value for the latin language + * @return self + */ + public function setLatin($latin) + { + $this->validateLocale($latin); + $this->latin = $latin; + return $this; + } + + /** + * Get the Latin Language + * + * @return string|null + */ + public function getLatin() + { + return $this->latin; + } + + /** + * Set the Language ID + * + * @param int $langId + * The value for the language ID + * @return self + * @see https://technet.microsoft.com/en-us/library/cc287874(v=office.12).aspx + */ + public function setLangId($langId) + { + $this->langId = $langId; + return $this; + } + + /** + * Get the Language ID + * + * @return int + */ + public function getLangId() + { + return $this->langId; + } + + /** + * Set the East Asian Language + * + * @param string $eastAsia + * The value for the east asian language + * @return self + */ + public function setEastAsia($eastAsia) + { + $this->validateLocale($eastAsia); + $this->eastAsia = $eastAsia; + return $this; + } + + /** + * Get the East Asian Language + * + * @return string|null + */ + public function getEastAsia() + { + return $this->eastAsia; + } + + /** + * Set the Complex Script Language + * + * @param string $bidirectional + * The value for the complex script language + * @return self + */ + public function setBidirectional($bidirectional) + { + $this->validateLocale($bidirectional); + $this->bidirectional = $bidirectional; + return $this; + } + + /** + * Get the Complex Script Language + * + * @return string|null + */ + public function getBidirectional() + { + return $this->bidirectional; + } + + /** + * Validates that the language passed is in the format xx-xx + * + * @param string $locale + * @return boolean + */ + private function validateLocale($locale) + { + if ($locale !== null && strstr($locale, '-') === false) { + throw new \InvalidArgumentException($locale . ' is not a valid language code'); + } + } +} diff --git a/src/PhpWord/Style/ListItem.php b/src/PhpWord/Style/ListItem.php index 18ea0bf264..61a8349bc9 100644 --- a/src/PhpWord/Style/ListItem.php +++ b/src/PhpWord/Style/ListItem.php @@ -247,11 +247,12 @@ private function getListTypeStyle() // Populate style and register to global Style register $style = $listTypeStyles[$this->listType]; + $numProperties = count($properties); foreach ($style['levels'] as $key => $value) { $level = array(); $levelProperties = explode(', ', $value); $level['level'] = $key; - for ($i = 0; $i < count($properties); $i++) { + for ($i = 0; $i < $numProperties; $i++) { $property = $properties[$i]; $level[$property] = $levelProperties[$i]; } diff --git a/src/PhpWord/Style/Paragraph.php b/src/PhpWord/Style/Paragraph.php index 8d34255000..169f2cdaf6 100644 --- a/src/PhpWord/Style/Paragraph.php +++ b/src/PhpWord/Style/Paragraph.php @@ -165,6 +165,13 @@ class Paragraph extends Border */ private $contextualSpacing = false; + /** + * Right to Left Paragraph Layout + * + * @var bool + */ + private $bidi = false; + /** * Set Style value * @@ -216,6 +223,7 @@ public function getStyleValues() 'tabs' => $this->getTabs(), 'shading' => $this->getShading(), 'contextualSpacing' => $this->hasContextualSpacing(), + 'bidi' => $this->isBidi(), ); return $styles; @@ -739,7 +747,7 @@ public function setShading($value = null) return $this; } - + /** * Get contextualSpacing * @@ -762,4 +770,28 @@ public function setContextualSpacing($contextualSpacing) return $this; } + + /** + * Get bidirectional + * + * @return bool + */ + public function isBidi() + { + return $this->bidi; + } + + /** + * Set bidi + * + * @param bool $bidi + * Set to true to write from right to left + * @return self + */ + public function setBidi($bidi) + { + $this->bidi = $bidi; + + return $this; + } } diff --git a/src/PhpWord/Style/TextBox.php b/src/PhpWord/Style/TextBox.php index 600fb8eabf..6783cd1898 100644 --- a/src/PhpWord/Style/TextBox.php +++ b/src/PhpWord/Style/TextBox.php @@ -183,7 +183,8 @@ public function hasInnerMargins() { $hasInnerMargins = false; $margins = $this->getInnerMargin(); - for ($i = 0; $i < count($margins); $i++) { + $numMargins = count($margins); + for ($i = 0; $i < $numMargins; $i++) { if ($margins[$i] !== null) { $hasInnerMargins = true; } diff --git a/src/PhpWord/Writer/ODText/Part/Styles.php b/src/PhpWord/Writer/ODText/Part/Styles.php index b50be0e804..ee22aaabb7 100644 --- a/src/PhpWord/Writer/ODText/Part/Styles.php +++ b/src/PhpWord/Writer/ODText/Part/Styles.php @@ -81,22 +81,27 @@ private function writeDefault(XMLWriter $xmlWriter) $xmlWriter->writeAttribute('style:writing-mode', 'page'); $xmlWriter->endElement(); // style:paragraph-properties + $language = $this->getParentWriter()->getPhpWord()->getSettings()->getThemeFontLang(); + $latinLang = $language != null && is_string($language->getLatin()) ? explode('-', $language->getLatin()) : array('fr', 'FR'); + $asianLang = $language != null && is_string($language->getEastAsia()) ? explode('-', $language->getEastAsia()) : array('zh', 'CN'); + $complexLang = $language != null && is_string($language->getBidirectional()) ? explode('-', $language->getBidirectional()) : array('hi', 'IN'); + // Font $xmlWriter->startElement('style:text-properties'); $xmlWriter->writeAttribute('style:use-window-font-color', 'true'); $xmlWriter->writeAttribute('style:font-name', Settings::getDefaultFontName()); $xmlWriter->writeAttribute('fo:font-size', Settings::getDefaultFontSize() . 'pt'); - $xmlWriter->writeAttribute('fo:language', 'fr'); - $xmlWriter->writeAttribute('fo:country', 'FR'); + $xmlWriter->writeAttribute('fo:language', $latinLang[0]); + $xmlWriter->writeAttribute('fo:country', $latinLang[1]); $xmlWriter->writeAttribute('style:letter-kerning', 'true'); $xmlWriter->writeAttribute('style:font-name-asian', Settings::getDefaultFontName() . '2'); $xmlWriter->writeAttribute('style:font-size-asian', Settings::getDefaultFontSize() . 'pt'); - $xmlWriter->writeAttribute('style:language-asian', 'zh'); - $xmlWriter->writeAttribute('style:country-asian', 'CN'); + $xmlWriter->writeAttribute('style:language-asian', $asianLang[0]); + $xmlWriter->writeAttribute('style:country-asian', $asianLang[1]); $xmlWriter->writeAttribute('style:font-name-complex', Settings::getDefaultFontName() . '2'); $xmlWriter->writeAttribute('style:font-size-complex', Settings::getDefaultFontSize() . 'pt'); - $xmlWriter->writeAttribute('style:language-complex', 'hi'); - $xmlWriter->writeAttribute('style:country-complex', 'IN'); + $xmlWriter->writeAttribute('style:language-complex', $complexLang[0]); + $xmlWriter->writeAttribute('style:country-complex', $complexLang[1]); $xmlWriter->writeAttribute('fo:hyphenate', 'false'); $xmlWriter->writeAttribute('fo:hyphenation-remain-char-count', '2'); $xmlWriter->writeAttribute('fo:hyphenation-push-char-count', '2'); diff --git a/src/PhpWord/Writer/RTF/Part/Document.php b/src/PhpWord/Writer/RTF/Part/Document.php index 24ee7b0add..97b2f1b611 100644 --- a/src/PhpWord/Writer/RTF/Part/Document.php +++ b/src/PhpWord/Writer/RTF/Part/Document.php @@ -86,6 +86,10 @@ private function writeInfo() */ private function writeFormatting() { + $docSettings = $this->getParentWriter()->getPhpWord()->getSettings(); + // Applies a language to a text run (defaults to 1036 : French (France)) + $langId = $docSettings->getThemeFontLang() != null && $docSettings->getThemeFontLang()->getLangId() != null ? $docSettings->getThemeFontLang()->getLangId() : 1036; + $content = ''; $content .= '\deftab720'; // Set the default tab size (720 twips) @@ -94,7 +98,7 @@ private function writeFormatting() $content .= '\uc1'; // Set the numberof bytes that follows a unicode character $content .= '\pard'; // Resets to default paragraph properties. $content .= '\nowidctlpar'; // No widow/orphan control - $content .= '\lang1036'; // Applies a language to a text run (1036 : French (France)) + $content .= '\lang' . $langId; $content .= '\kerning1'; // Point size (in half-points) above which to kern character pairs $content .= '\fs' . (Settings::getDefaultFontSize() * 2); // Set the font size in half-points $content .= PHP_EOL; diff --git a/src/PhpWord/Writer/Word2007/Part/Settings.php b/src/PhpWord/Writer/Word2007/Part/Settings.php index d2cb81179f..eca70d29fa 100644 --- a/src/PhpWord/Writer/Word2007/Part/Settings.php +++ b/src/PhpWord/Writer/Word2007/Part/Settings.php @@ -17,9 +17,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Part; -use PhpOffice\PhpWord\Settings as DocumentSettings; use PhpOffice\PhpWord\ComplexType\ProofState; use PhpOffice\PhpWord\ComplexType\TrackChangesView; +use PhpOffice\PhpWord\Style\Language; /** * Word2007 settings part writer: word/settings.xml @@ -110,7 +110,6 @@ private function getSettings() 'w:defaultTabStop' => array('@attributes' => array('w:val' => '708')), 'w:hyphenationZone' => array('@attributes' => array('w:val' => '425')), 'w:characterSpacingControl' => array('@attributes' => array('w:val' => 'doNotCompress')), - 'w:themeFontLang' => array('@attributes' => array('w:val' => 'en-US')), 'w:decimalSymbol' => array('@attributes' => array('w:val' => $documentSettings->getDecimalSymbol())), 'w:listSeparator' => array('@attributes' => array('w:val' => ';')), 'w:compat' => array(), @@ -152,6 +151,7 @@ private function getSettings() $this->setOnOffValue('w:doNotTrackFormatting', $documentSettings->hasDoNotTrackFormatting()); $this->setOnOffValue('w:evenAndOddHeaders', $documentSettings->hasEvenAndOddHeaders()); + $this->setThemeFontLang($documentSettings->getThemeFontLang()); $this->setRevisionView($documentSettings->getRevisionView()); $this->setDocumentProtection($documentSettings->getDocumentProtection()); $this->setProofState($documentSettings->getProofState()); @@ -179,7 +179,7 @@ private function setOnOffValue($settingName, $booleanValue) /** * Get protection settings. * - * @param \PhpOffice\PhpWord\Metadata\Settings $documentProtection + * @param \PhpOffice\PhpWord\Metadata\Protection $documentProtection * @return void */ private function setDocumentProtection($documentProtection) @@ -212,9 +212,9 @@ private function setProofState(ProofState $proofState = null) } /** - * Set the Proof state + * Set the Revision View * - * @param ProofState $proofState + * @param TrackChangesView $trackChangesView */ private function setRevisionView(TrackChangesView $trackChangesView = null) { @@ -229,6 +229,23 @@ private function setRevisionView(TrackChangesView $trackChangesView = null) } } + /** + * Sets the language + * + * @param Language $language + */ + private function setThemeFontLang(Language $language = null) + { + $latinLanguage = ($language == null || $language->getLatin() === null) ? 'en-US' : $language->getLatin(); + $lang = array(); + $lang['w:val'] = $latinLanguage; + if ($language != null) { + $lang['w:eastAsia'] = $language->getEastAsia() === null ? 'x-none' : $language->getEastAsia(); + $lang['w:bidi'] = $language->getBidirectional() === null ? 'x-none' : $language->getBidirectional(); + } + $this->settings['w:themeFontLang'] = array('@attributes' => $lang); + } + /** * Set the magnification * diff --git a/src/PhpWord/Writer/Word2007/Part/Styles.php b/src/PhpWord/Writer/Word2007/Part/Styles.php index 01b84c0815..7795d56b49 100644 --- a/src/PhpWord/Writer/Word2007/Part/Styles.php +++ b/src/PhpWord/Writer/Word2007/Part/Styles.php @@ -85,6 +85,8 @@ private function writeDefaultStyles(XMLWriter $xmlWriter, $styles) { $fontName = PhpWordSettings::getDefaultFontName(); $fontSize = PhpWordSettings::getDefaultFontSize(); + $language = $this->getParentWriter()->getPhpWord()->getSettings()->getThemeFontLang(); + $latinLanguage = ($language == null || $language->getLatin() === null) ? 'en-US' : $language->getLatin(); // Default font $xmlWriter->startElement('w:docDefaults'); @@ -102,6 +104,13 @@ private function writeDefaultStyles(XMLWriter $xmlWriter, $styles) $xmlWriter->startElement('w:szCs'); $xmlWriter->writeAttribute('w:val', $fontSize * 2); $xmlWriter->endElement(); // w:szCs + $xmlWriter->startElement('w:lang'); + $xmlWriter->writeAttribute('w:val', $latinLanguage); + if ($language != null) { + $xmlWriter->writeAttributeIf($language->getEastAsia() !== null, 'w:eastAsia', $language->getEastAsia()); + $xmlWriter->writeAttributeIf($language->getBidirectional() !== null, 'w:bidi', $language->getBidirectional()); + } + $xmlWriter->endElement(); // w:lang $xmlWriter->endElement(); // w:rPr $xmlWriter->endElement(); // w:rPrDefault $xmlWriter->endElement(); // w:docDefaults diff --git a/src/PhpWord/Writer/Word2007/Style/AbstractStyle.php b/src/PhpWord/Writer/Word2007/Style/AbstractStyle.php index d0ee5a0def..0b8b0a52aa 100644 --- a/src/PhpWord/Writer/Word2007/Style/AbstractStyle.php +++ b/src/PhpWord/Writer/Word2007/Style/AbstractStyle.php @@ -71,7 +71,7 @@ protected function getXmlWriter() /** * Get Style * - * @return \PhpOffice\PhpWord\Style\AbstractStyle + * @return string|\PhpOffice\PhpWord\Style\AbstractStyle */ protected function getStyle() { diff --git a/src/PhpWord/Writer/Word2007/Style/Font.php b/src/PhpWord/Writer/Word2007/Style/Font.php index 97cf3088b9..2248a4485f 100644 --- a/src/PhpWord/Writer/Word2007/Style/Font.php +++ b/src/PhpWord/Writer/Word2007/Style/Font.php @@ -86,6 +86,16 @@ private function writeStyle() $xmlWriter->endElement(); } + //Language + $language = $style->getLang(); + if ($language != null && ($language->getLatin() !== null || $language->getEastAsia() !== null || $language->getBidirectional() !== null)) { + $xmlWriter->startElement('w:lang'); + $xmlWriter->writeAttributeIf($language->getLatin() !== null, 'w:val', $language->getLatin()); + $xmlWriter->writeAttributeIf($language->getEastAsia() !== null, 'w:eastAsia', $language->getEastAsia()); + $xmlWriter->writeAttributeIf($language->getBidirectional() !== null, 'w:bidi', $language->getBidirectional()); + $xmlWriter->endElement(); + } + // Color $color = $style->getColor(); $xmlWriter->writeElementIf($color !== null, 'w:color', 'w:val', $color); diff --git a/src/PhpWord/Writer/Word2007/Style/Paragraph.php b/src/PhpWord/Writer/Word2007/Style/Paragraph.php index 787f2a5f7f..32f8abbaaa 100644 --- a/src/PhpWord/Writer/Word2007/Style/Paragraph.php +++ b/src/PhpWord/Writer/Word2007/Style/Paragraph.php @@ -106,7 +106,10 @@ private function writeStyle() } $xmlWriter->endElement(); } - + + //Right to left + $xmlWriter->writeElementIf($styles['bidi'] === true, 'w:bidi'); + //Paragraph contextualSpacing $xmlWriter->writeElementIf($styles['contextualSpacing'] === true, 'w:contextualSpacing'); diff --git a/tests/PhpWord/ComplexType/FootnotePropertiesTest.php b/tests/PhpWord/ComplexType/FootnotePropertiesTest.php index 39392fcd0b..aa46d89be2 100644 --- a/tests/PhpWord/ComplexType/FootnotePropertiesTest.php +++ b/tests/PhpWord/ComplexType/FootnotePropertiesTest.php @@ -21,9 +21,9 @@ use PhpOffice\PhpWord\SimpleType\NumberFormat; /** - * Test class for PhpOffice\PhpWord\SimpleType\FootnoteProperties + * Test class for PhpOffice\PhpWord\ComplexType\FootnoteProperties * - * @coversDefaultClass \PhpOffice\PhpWord\SimpleType\FootnoteProperties + * @coversDefaultClass \PhpOffice\PhpWord\ComplexType\FootnoteProperties * @runTestsInSeparateProcesses */ class FootnotePropertiesTest extends \PHPUnit_Framework_TestCase diff --git a/tests/PhpWord/ComplexType/ProofStateTest.php b/tests/PhpWord/ComplexType/ProofStateTest.php new file mode 100644 index 0000000000..0b7e74ca89 --- /dev/null +++ b/tests/PhpWord/ComplexType/ProofStateTest.php @@ -0,0 +1,61 @@ +setGrammar(ProofState::CLEAN); + $pState->setSpelling(ProofState::DIRTY); + + $this->assertEquals(ProofState::CLEAN, $pState->getGrammar()); + $this->assertEquals(ProofState::DIRTY, $pState->getSpelling()); + } + + /** + * Test throws exception if wrong grammar proof state value given + * + * @expectedException \InvalidArgumentException + */ + public function testWrongGrammar() + { + $pState = new ProofState(); + $pState->setGrammar('Wrong'); + } + + /** + * Test throws exception if wrong spelling proof state value given + * + * @expectedException \InvalidArgumentException + */ + public function testWrongSpelling() + { + $pState= new ProofState(); + $pState->setSpelling('Wrong'); + } +} diff --git a/tests/PhpWord/Style/FontTest.php b/tests/PhpWord/Style/FontTest.php index 61648d4ebf..c8fd4dab6a 100644 --- a/tests/PhpWord/Style/FontTest.php +++ b/tests/PhpWord/Style/FontTest.php @@ -74,6 +74,7 @@ public function testSetStyleValueWithNullOrEmpty() 'scale' => null, 'spacing' => null, 'kerning' => null, + 'lang' => null, ); foreach ($attributes as $key => $default) { $get = is_bool($default) ? "is{$key}" : "get{$key}"; diff --git a/tests/PhpWord/Style/LanguageTest.php b/tests/PhpWord/Style/LanguageTest.php new file mode 100644 index 0000000000..bd4669568e --- /dev/null +++ b/tests/PhpWord/Style/LanguageTest.php @@ -0,0 +1,62 @@ + array(null, 'fr-BE'), + 'eastAsia' => array(null, 'ja-JP'), + 'bidirectional' => array(null, 'ar-SA'), + 'langId' => array(null, 1036), + ); + foreach ($properties as $property => $value) { + list($default, $expected) = $value; + $get = "get{$property}"; + $set = "set{$property}"; + + $this->assertEquals($default, $object->$get()); // Default value + + $object->$set($expected); + + $this->assertEquals($expected, $object->$get()); // New value + } + } + + /** + * Test throws exception if wrong locale is given + * + * @expectedException \InvalidArgumentException + */ + public function testWrongLanguage() + { + $language = new Language(); + $language->setLatin('fr'); + } +} diff --git a/tests/PhpWord/Style/ParagraphTest.php b/tests/PhpWord/Style/ParagraphTest.php index 86d6e89607..b78c557a04 100644 --- a/tests/PhpWord/Style/ParagraphTest.php +++ b/tests/PhpWord/Style/ParagraphTest.php @@ -80,6 +80,7 @@ public function testSetStyleValueNormal() 'keepLines' => true, 'pageBreakBefore' => true, 'contextualSpacing' => true, + 'bidi' => true, ); foreach ($attributes as $key => $value) { $get = $this->findGetter($key, $value, $object); diff --git a/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php b/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php index 828e12835c..99c66680ff 100644 --- a/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php @@ -16,11 +16,12 @@ */ namespace PhpOffice\PhpWord\Writer\Word2007\Part; +use PhpOffice\PhpWord\ComplexType\TrackChangesView; use PhpOffice\PhpWord\PhpWord; -use PhpOffice\PhpWord\TestHelperDOCX; use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\SimpleType\Zoom; -use PhpOffice\PhpWord\ComplexType\TrackChangesView; +use PhpOffice\PhpWord\Style\Language; +use PhpOffice\PhpWord\TestHelperDOCX; /** * Test class for PhpOffice\PhpWord\Writer\Word2007\Part\Settings @@ -73,7 +74,7 @@ public function testCompatibility() /** * Test language */ - public function testLanguage() + public function testDefaultLanguage() { $phpWord = new PhpWord(); @@ -88,6 +89,26 @@ public function testLanguage() $this->assertEquals('en-US', $element->getAttribute('w:val')); } + /** + * Test language + */ + public function testLanguage() + { + $phpWord = new PhpWord(); + $phpWord->getSettings()->setThemeFontLang(new Language(Language::DE_DE, Language::KO_KR, Language::HE_IL)); + $doc = TestHelperDOCX::getDocument($phpWord); + + $file = 'word/settings.xml'; + + $path = '/w:settings/w:themeFontLang'; + $this->assertTrue($doc->elementExists($path, $file)); + $element = $doc->getElement($path, $file); + + $this->assertEquals(Language::DE_DE, $element->getAttribute('w:val')); + $this->assertEquals(Language::KO_KR, $element->getAttribute('w:eastAsia')); + $this->assertEquals(Language::HE_IL, $element->getAttribute('w:bidi')); + } + /** * Test spelling */