stack [$this->size] = new ODTElementRoot(); $this->size++; } /** * Get current list item. * If the function returns NULL then that means that we are * currently not in a list item. * * @return ODTStateElement|NULL */ public function getCurrentListItem() { return $this->findClosestWithClass ('list-item'); } /** * Get current frame. * If the function returns NULL then that means that we are * currently not in a frame. * * @return ODTStateElement|NULL */ public function getCurrentFrame() { return $this->findClosestWithClass ('frame'); } /** * Get current list. * If the function returns NULL then that means that we are * currently not in a list. * * @return ODTStateElement|NULL */ public function getCurrentList() { return $this->findClosestWithClass ('list'); } /** * Get current paragraph. * If the function returns NULL then that means that we are * currently not in a paragraph. * * @return ODTStateElement|NULL */ public function getCurrentParagraph() { // Only search for the paragraph if the current element tells // us that we are in one. Otherwise we may find the paragraph // around this current element which might lead to double // closing of a paragraph == invalid/broken ODT document! if ($this->getInParagraph()) { return $this->findClosestWithClass ('paragraph'); } return NULL; } /** * Get current table. * If the function returns NULL then that means that we are * currently not in a table. * * @return ODTStateElement|NULL */ public function getCurrentTable() { return $this->findClosestWithClass ('table'); } /** * Enter a new state with element name $element and class $clazz. * E.g. 'text:p' and 'paragraph'. * * @param string $element * @param string $clazz */ public function enter(ODTStateElement $element, $attributes=NULL) { if ( !isset($element) ) { return; } $name = $element->getElementName(); // Increase the counter for that element if ( !isset($this->element_counter [$name]) ) { $this->element_counter [$name] = 1; } else { $this->element_counter [$name]++; } $element->setCount($this->element_counter [$name]); // Get the current element $previous = $this->stack [$this->size-1]; // Add new element to stack $this->stack [$this->size] = $element; $this->size++; // Set the elements style object if (isset($this->document)) { $styleObj = $this->document->getStyle($element->getStyleName()); $element->setStyle($styleObj); } // Let the element find its parent $element->determineParent ($previous); } /** * Get current element on top of the stack. * * @return ODTStateElement */ public function getCurrent() { return $this->stack [$this->size-1]; } /** * Leave current state. All data of the curent state is thrown away. */ public function leave() { // We always will keep the initial state. // That means we do nothing if size is 0. This would be a fault anyway. if ($this->size > 1) { unset ($this->stack [$this->size-1]); $this->size--; } } /** * Reset the state stack/go back to the initial state. * All states except the root state will be discarded. */ public function reset() { // Throw away any states except the initial state. // Reset size to 1. for ($reset = 1 ; $reset < $this->size ; $reset++) { unset ($this->stack [$reset]); } $this->size = 1; } /** * Find the closest state with class $clazz. * * @param string $clazz * @return ODTStateEntry|NULL */ public function findClosestWithClass($clazz) { for ($search = $this->size-1 ; $search > 0 ; $search--) { if ($this->stack [$search]->getClass() == $clazz) { return $this->stack [$search]; } } // Nothing found. return NULL; } /** * Find the closest state with class $clazz, return $index. * * @param string $clazz * @param integer|false &$index Index of the found element or false * @return ODTStateEntry|NULL */ public function findClosestWithClassGetIndex($clazz, &$index) { $index = false; for ($search = $this->size-1 ; $search > 0 ; $search--) { if ($this->stack [$search]->getClass() == $clazz) { $index = $search; return $this->stack [$search]; } } // Nothing found. return NULL; } /** * toString() function. Only for creating debug dumps. * * @return string */ public function toString () { $indent = ''; $string = "Stackdump:\n"; for ($search = 0 ; $search < $this->size ; $search++) { $string .= $indent . $this->stack [$search]->getElementName().";\n"; $indent .= ' '; } return $string; } /** * Find the closest state with class $clazz. * * @param string $clazz * @return ODTStateEntry|NULL */ public function countClass($clazz) { $count = 0; for ($search = $this->size-1 ; $search > 0 ; $search--) { if ($this->stack [$search]->getClass() == $clazz) { $count++; } } return $count; } /** * Find the closest element with element name $name. * * @param string $name * @return ODTStateElement|NULL */ public function findClosestWithName($name) { for ($search = $this->size-1 ; $search > 0 ; $search--) { if ($this->stack [$search]->getElementName() == $name) { return $this->stack [$search]; } } // Nothing found. return NULL; } /** * Are we in a table row? * * @return bool */ public function getInTableRow() { $this->findClosestWithClassGetIndex('table-row', $tableRowIndex); $this->findClosestWithClassGetIndex('table', $tableIndex); if ($tableRowIndex > $tableIndex) { return true; } return false; } /** * Are we in a table cell? * * @return bool */ public function getInTableCell() { $this->findClosestWithClassGetIndex('table-cell', $tableCellIndex); $this->findClosestWithClassGetIndex('table-row', $tableRowIndex); if ($tableCellIndex > $tableRowIndex) { return true; } return false; } /** * Are we in a list item? * * @return bool */ public function getInListItem() { $this->findClosestWithClassGetIndex('list-item', $listItemIndex); $this->findClosestWithClassGetIndex('list', $listIndex); if ($listItemIndex > $listIndex) { return true; } return false; } /** * Are we in list content? * * @return bool */ public function getInListContent() { // listContentOpen == paragraphOpen, // so we can simply call getInParagraph() return $this->getInParagraph(); } /** * Are we in a paragraph? * * @return bool */ public function getInParagraph() { // Ask the current element if ($this->size > 0) { return $this->stack [$this->size-1]->getInParagraph(); } else { return false; } } /** * Set the ODTDocument to which this state belongs. * * @param ODTDocument $doc */ public function setDocument($doc) { $this->document = $doc; } public function getHTMLElement() { // Ask the current element if ($this->size > 0) { return $this->stack [$this->size-1]->getHTMLElement(); } else { return NULL; } } public function getElementCount($element) { return $this->element_counter [$element]++; } }