PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/Document/src/converters/element_visitor/docbook/odt/styler/pcss/generator/list.php

https://github.com/Yannix/zetacomponents
PHP | 370 lines | 193 code | 32 blank | 145 comment | 14 complexity | 3b0f7e620a60b89ef92290a1bd728c27 MD5 | raw file
  1. <?php
  2. /**
  3. * File containing the ezcDocumentOdtListStyleGenerator class.
  4. *
  5. * Licensed to the Apache Software Foundation (ASF) under one
  6. * or more contributor license agreements. See the NOTICE file
  7. * distributed with this work for additional information
  8. * regarding copyright ownership. The ASF licenses this file
  9. * to you under the Apache License, Version 2.0 (the
  10. * "License"); you may not use this file except in compliance
  11. * with the License. You may obtain a copy of the License at
  12. *
  13. * http://www.apache.org/licenses/LICENSE-2.0
  14. *
  15. * Unless required by applicable law or agreed to in writing,
  16. * software distributed under the License is distributed on an
  17. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  18. * KIND, either express or implied. See the License for the
  19. * specific language governing permissions and limitations
  20. * under the License.
  21. *
  22. * @package Document
  23. * @version //autogen//
  24. * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
  25. * @access private
  26. */
  27. /**
  28. * Class to generate styles for lists (<text:list/>).
  29. *
  30. * @package Document
  31. * @access private
  32. * @version //autogen//
  33. */
  34. class ezcDocumentOdtListStyleGenerator extends ezcDocumentOdtStyleGenerator
  35. {
  36. /**
  37. * Text style generator.
  38. *
  39. * @var ezcDocumentOdtTextStyleGenerator
  40. */
  41. protected $textStyleGenerator;
  42. /**
  43. * List property generator.
  44. *
  45. * @var ezcDocumentOdtStyleListPropertyGenerator
  46. */
  47. protected $listPropertyGenerator;
  48. /**
  49. * List IDs.
  50. *
  51. * @var int
  52. */
  53. protected $id = 0;
  54. /**
  55. * Creates a new style genertaor.
  56. *
  57. * @param ezcDocumentOdtPcssConverterManager $styleConverters
  58. */
  59. public function __construct( ezcDocumentOdtPcssConverterManager $styleConverters )
  60. {
  61. parent::__construct( $styleConverters );
  62. $this->textStyleGenerator = new ezcDocumentOdtTextStyleGenerator(
  63. $styleConverters
  64. );
  65. $this->listPropertyGenerator = new ezcDocumentOdtStyleListPropertyGenerator(
  66. $styleConverters
  67. );
  68. }
  69. /**
  70. * Returns if the given $odtElement is handled by this generator.
  71. *
  72. * @param DOMElement $odtElement
  73. * @return bool
  74. */
  75. public function handles( DOMElement $odtElement )
  76. {
  77. return (
  78. $odtElement->localName === 'list'
  79. );
  80. }
  81. /**
  82. * Creates the styles with $styleAttributes for the given $odtElement.
  83. *
  84. * @param ezcDocumentOdtStyleInformation $styleInfo
  85. * @param DOMElement $odtElement
  86. * @param array(string=>ezcDocumentPcssStyleValue) $styleAttributes
  87. */
  88. public function createStyle( ezcDocumentOdtStyleInformation $styleInfo, DOMElement $odtElement, array $styleAttributes )
  89. {
  90. $baseListDef = $this->getBaseList( $odtElement );
  91. if ( $baseListDef['list'] === null )
  92. {
  93. $listStyle = $this->createNewListStyle( $odtElement, $styleInfo );
  94. $level = 1;
  95. }
  96. else
  97. {
  98. $listStyle = $this->retrieveListStyle( $baseListDef['list'], $styleInfo );
  99. $level = $baseListDef['depth'];
  100. }
  101. $this->createListLevelStyle( $styleInfo, $listStyle, $level, $styleAttributes );
  102. }
  103. /**
  104. * Creates a style for the <text:list /> element.
  105. *
  106. * Checks if the list is nested in a different list. If this is not the
  107. * case, a new list style is generated. Otherwise, the existing list style
  108. * is retrieved and a list definition for the corresponding nesting depth
  109. * is created.
  110. *
  111. * @param ezcDocumentOdtStyleInformation $styleInfo
  112. * @param DOMElement $list
  113. * @param array $styleAttributes
  114. * @return void
  115. */
  116. protected function createListStyle( ezcDocumentOdtStyleInformation $styleInfo, DOMElement $list, array $styleAttributes )
  117. {
  118. }
  119. /**
  120. * Creates a new <text:list-style/> and applies it to the given
  121. * $odtElement.
  122. *
  123. * This method creates and returns a new list style DOMElement in
  124. * $styleInfo for $odtElement and assigns its name to the $odtElement. The
  125. * list style can then be filled with list properties of different levels.
  126. *
  127. * @param DOMElement $odtElement
  128. * @param ezcDocumentOdtStyleInformation $styleInfo
  129. * @return DOMElement
  130. */
  131. protected function createNewListStyle( DOMElement $odtElement, ezcDocumentOdtStyleInformation $styleInfo )
  132. {
  133. $listStyle = $styleInfo->automaticStyleSection->appendChild(
  134. $styleInfo->automaticStyleSection->ownerDocument->createElementNS(
  135. ezcDocumentOdt::NS_ODT_TEXT,
  136. 'text:list-style'
  137. )
  138. );
  139. $listStyle->setAttributeNS(
  140. ezcDocumentOdt::NS_ODT_STYLE,
  141. 'style:name',
  142. ( $styleName = $this->getUniqueStyleName( 'l' ) )
  143. );
  144. $odtElement->setAttributeNS(
  145. ezcDocumentOdt::NS_ODT_TEXT,
  146. 'text:style-name',
  147. $styleName
  148. );
  149. // OOO attaches IDs to root lists, so do we.
  150. $odtElement->setAttributeNS(
  151. ezcDocumentOdt::NS_XML,
  152. 'xml:id',
  153. sprintf( "%s%s", 'list', ++$this->id )
  154. );
  155. return $listStyle;
  156. }
  157. /**
  158. * Creates the <text:list-level-style-* /> element for $styleAttributes.
  159. *
  160. * This method creates a list-level-style in $listStyle for the given list
  161. * $level applying $styleAttributes to this list level.
  162. *
  163. * @param ezcDocumentOdtStyleInformation $styleInfo
  164. * @param DOMElement $listStyle
  165. * @param int $level
  166. * @param array $styleAttributes
  167. */
  168. protected function createListLevelStyle( ezcDocumentOdtStyleInformation $styleInfo, DOMElement $listStyle, $level, array $styleAttributes )
  169. {
  170. $styleAttributes = $this->calculateListLevelMeasures(
  171. $listStyle,
  172. $level,
  173. $styleAttributes
  174. );
  175. $listLevelStyle = $listStyle->appendChild(
  176. $listStyle->ownerDocument->createElementNS(
  177. ezcDocumentOdt::NS_ODT_TEXT,
  178. 'text:list-level-style-' . $styleAttributes['list-type']->value
  179. )
  180. );
  181. $listLevelStyle->setAttributeNS(
  182. ezcDocumentOdt::NS_ODT_TEXT,
  183. 'level',
  184. $level
  185. );
  186. // Creates the text:style-name attribute with a new style that is
  187. // applied to the bullet/numbering.
  188. $this->textStyleGenerator->createStyle(
  189. $styleInfo,
  190. $listLevelStyle,
  191. $styleAttributes
  192. );
  193. // Set by OOO no matter if bullet or number list
  194. // @todo: Make styleable
  195. $listLevelStyle->setAttributeNS(
  196. ezcDocumentOdt::NS_ODT_STYLE,
  197. 'style:num-suffix',
  198. '.'
  199. );
  200. $this->listPropertyGenerator->createProperty(
  201. $listLevelStyle,
  202. $styleAttributes
  203. );
  204. if ( $styleAttributes['list-type']->value === 'bullet' )
  205. {
  206. $listLevelStyle->setAttributeNS(
  207. ezcDocumentOdt::NS_ODT_TEXT,
  208. 'text:bullet-char',
  209. $styleAttributes['list-bullet']->value
  210. );
  211. }
  212. else
  213. {
  214. $listLevelStyle->setAttributeNS(
  215. ezcDocumentOdt::NS_ODT_STYLE,
  216. 'style:num-format',
  217. $styleAttributes['list-number']->value
  218. );
  219. }
  220. }
  221. /**
  222. * Calculates the list margin and indent.
  223. *
  224. * Margin and indent are handled in a strange way in ODF. This method
  225. * calculates the margin for a list level, based on the previous level margin
  226. * and the current margin and padding. In addition, the text-indent is set
  227. * to fit the previous list-level. The new $styleAttributes are returned.
  228. *
  229. * @param DOMElement $listStyle
  230. * @param int $level
  231. * @param array $styleAttributes
  232. * @return array(string=>float)
  233. */
  234. protected function calculateListLevelMeasures( DOMElement $listStyle, $level, $styleAttributes )
  235. {
  236. $previousMargin = 0;
  237. foreach( $listStyle->childNodes as $listStyleChild )
  238. {
  239. if ( $listStyleChild->nodeType === XML_ELEMENT_NODE
  240. && strpos( $listStyleChild->localName, 'list-level-style-' ) === 0
  241. && $listStyleChild->hasAttributeNS( ezcDocumentOdt::NS_ODT_TEXT, 'level' )
  242. && $listStyleChild->getAttributeNS( ezcDocumentOdt::NS_ODT_TEXT, 'level' ) == ( $level - 1 )
  243. )
  244. {
  245. $alignementProps = $listStyleChild->getElementsByTagNameNS(
  246. ezcDocumentOdt::NS_ODT_STYLE,
  247. 'list-level-label-alignment'
  248. );
  249. if ( $alignementProps->length === 1 )
  250. {
  251. $previousMargin = (int) $alignementProps->item( 0 )->getAttributeNS(
  252. ezcDocumentOdt::NS_ODT_FO,
  253. 'margin-left'
  254. );
  255. }
  256. break;
  257. }
  258. }
  259. $styleAttributes['margin']->value['left'] = $previousMargin
  260. + ( $margin = $styleAttributes['margin']->value['left'] )
  261. + ( $padding = $styleAttributes['padding']->value['left'] );
  262. $styleAttributes['text-indent'] = new ezcDocumentPcssStyleMeasureValue(
  263. - ( $margin + $padding )
  264. );
  265. return $styleAttributes;
  266. }
  267. /**
  268. * Returns the <text:list-style> DOMElement assigned to $odtList.
  269. *
  270. * @param DOMElement $odtList
  271. * @param ezcDocumentOdtStyleInformation $styleInfo
  272. * @return DOMElement
  273. */
  274. protected function retrieveListStyle( $odtList, ezcDocumentOdtStyleInformation $styleInfo )
  275. {
  276. $styleName = $odtList->getAttributeNS(
  277. ezcDocumentOdt::NS_ODT_TEXT,
  278. 'style-name'
  279. );
  280. $xpath = new DOMXpath( $styleInfo->automaticStyleSection->ownerDocument );
  281. $xpath->registerNamespace( ezcDocumentOdt::NS_ODT_TEXT, 'text' );
  282. $xpath->registerNamespace( ezcDocumentOdt::NS_ODT_STYLE, 'style' );
  283. $styleList = $xpath->query(
  284. "text:list-style[@style:name='{$styleName}']",
  285. $styleInfo->automaticStyleSection
  286. );
  287. if ( $styleList->length !== 1 )
  288. {
  289. throw new RuntimeException(
  290. "Inconsistent style section. Found {$styleList->length} list styles with name '{$styleName}'"
  291. );
  292. }
  293. return $styleList->item( 0 );
  294. }
  295. /**
  296. * Returns the parent <text:list/> element or null.
  297. *
  298. * This method returns the parent <text:list/> element for the given $list and the nesting depth of $list,
  299. * if it is nested in another list. The returned structure is:
  300. *
  301. * <code>
  302. * <?php
  303. * array(
  304. * 'base' => <DOMElement|null>,
  305. * 'depth' => <int>
  306. * );
  307. * ?>
  308. * </code>
  309. *
  310. * @param DOMElement $list
  311. * @param int $depth
  312. * @return array
  313. */
  314. protected function getBaseList( DOMElement $list, $depth = 1 )
  315. {
  316. $parent = $list->parentNode;
  317. if ( $parent === null || $parent->nodeType === XML_DOCUMENT_NODE )
  318. {
  319. return array(
  320. 'list' => null,
  321. 'depth' => $depth
  322. );
  323. }
  324. if ( $parent->nodeType === XML_ELEMENT_NODE && $parent->localName === 'list' )
  325. {
  326. ++$depth;
  327. if ( $parent->hasAttributeNs( ezcDocumentOdt::NS_ODT_TEXT, 'style-name' ) )
  328. {
  329. return array(
  330. 'list' => $parent,
  331. 'depth' => $depth
  332. );
  333. }
  334. }
  335. return $this->getBaseList( $parent, $depth );
  336. }
  337. }
  338. ?>