Пример #1
0
 public static function getInstance()
 {
     if (IdmlHyperlinkManager::$instance == null) {
         IdmlHyperlinkManager::$instance = new IdmlHyperlinkManager();
     }
     return IdmlHyperlinkManager::$instance;
 }
 /**
  * Parse from DOM node.
  *
  * @param DOMElement $node
  */
 public function parse(DOMElement $node)
 {
     parent::parse($node);
     $hyperlinkMgr = IdmlHyperlinkManager::getInstance();
     // Set the id attribute value
     $destinationKey = $this->contextualStyle->idmlKeyValues['DestinationUniqueKey'];
     $this->id = 'Hyperlink_' . $destinationKey;
     // Save this destination in the hyperlink manager.
     // After parsing the page completes, its id must be stored for all the hyperlink destinations on the page.
     $hyperlinkMgr->saveDestinationForPageData($this->id);
 }
Пример #3
0
 /** The readDesignMap function obtains the filename pointers to the MasterSpreads, Resources, Spreads,
  *  Stories, and XML from the designmap, which is the manifest that contains references to the names and locations
  *  of the package's XML files. 
  * 
  * @return boolean true on success, false on failure.
  */
 public function readDesignMap()
 {
     //first read the BackStory.xml file to see if any Stories, Hyperlinks, etc. should be ignored ...
     $this->readBackingStoryAndSetHiddenIds();
     // The designmap contains references to everything in the package
     $designmap = $this->tempDir . '/designmap.xml';
     if (!file_exists($designmap)) {
         $this->idmlAssembler->getProgressUpdater()->setWarning("{$designmap} does not exist.");
         return false;
     }
     // create DOMDocument and DOMXPath objects
     $doc = new DomDocument();
     $b = $doc->load($designmap);
     if ($b === false) {
         return false;
     }
     $xpath = new DOMXPath($doc);
     // Parse the preferences file, which contains the width and height of our pages
     $tags = $xpath->query('//idPkg:Preferences');
     assert($tags->length == 1);
     $attr = $tags->item(0)->attributes->getNamedItem('src');
     $filename = "{$this->tempDir}/{$attr->value}";
     $this->preferences = new IdmlPreferences();
     $this->preferences->load($filename);
     IdmlAssembler::updateBookSize($this->preferences->pageWidth, $this->preferences->pageHeight);
     // The Declaration Manager deals with declared Colors, declared Styles, and declared Style Groups
     $manager = IdmlDeclarationManager::getInstance();
     // Parse the graphics file which contains color declarations (this must be done before parsing the Styles)
     $tags = $xpath->query('//idPkg:Graphic');
     assert($tags->length == 1);
     $attr = $tags->item(0)->attributes->getNamedItem('src');
     $filename = "{$this->tempDir}/{$attr->value}";
     $manager->loadDeclaredColors($filename);
     // There should always be exactly one Styles file   *** Version 2: non-PEARSON ***
     $tags = $xpath->query('//idPkg:Styles');
     assert($tags->length == 1);
     $attr = $tags->item(0)->attributes->getNamedItem('src');
     $filename = "{$this->tempDir}/{$attr->value}";
     $manager->loadDeclaredStyles($filename);
     /*        // There should always be exactly one Styles file    *** Version 1: PEARSON PXE ***
             $tags = $xpath->query('//idPkg:Styles');
             assert( $tags->length == 1 );
             $attr = $tags->item(0)->attributes->getNamedItem('src');
             $filename = "{$this->tempDir}/{$attr->value}";
             $this->style = new IdmlStyles($this);
             $this->style->filename = $filename;
             $this->style->load();
     */
     // Parse fonts file.
     $tags = $xpath->query('//idPkg:Fonts');
     assert($tags->length == 1);
     $attr = $tags->item(0)->attributes->getNamedItem('src');
     $filename = "{$this->tempDir}/{$attr->value}";
     IdmlFontManager::getInstance()->loadFonts($filename);
     // There should always be exactly one Tags file
     $tags = $xpath->query('//idPkg:Tags');
     assert($tags->length == 1);
     $attr = $tags->item(0)->attributes->getNamedItem('src');
     $filename = "{$this->tempDir}/{$attr->value}";
     $this->tags = new IdmlTags($this);
     $this->tags->filename = $filename;
     $this->tags->load();
     // There are possibly several MasterSpread files, which are referenced by real spreads and accessed by their UID's.
     $tags = $xpath->query('//idPkg:MasterSpread');
     foreach ($tags as $tag) {
         $attr = $tag->attributes->getNamedItem('src');
         $filename = "{$this->tempDir}/{$attr->value}";
         $matches = null;
         $found = preg_match('|MasterSpreads/MasterSpread_(.*)\\.xml|', $attr->value, $matches);
         // u154 <-- MasterSpreads/MasterSpread_u154.xml
         if ($found == 1) {
             $UID = $matches[1];
             $masterSpread = new IdmlMasterSpread($this);
             $masterSpread->filename = $filename;
             $this->masterSpreads[$UID] = $masterSpread;
         } else {
             $this->idmlAssembler->getProgressUpdater()->setWarning("Unable to determine UID for MasterSpread '{$attr->value}'.");
         }
     }
     // There are most likely many Spread files, and they are ordered in the designmap
     // according to the book's page ordering.
     $tags = $xpath->query('//idPkg:Spread');
     foreach ($tags as $tag) {
         $attr = $tag->attributes->getNamedItem('src');
         $filename = "{$this->tempDir}/{$attr->value}";
         $spread = new IdmlSpread($this);
         $spread->filename = $filename;
         $this->spreads[] = $spread;
     }
     // There are most likely many Story files, which are referenced by TextFrames and accessed by a parentStoryUID.
     $tags = $xpath->query('//idPkg:Story');
     foreach ($tags as $tag) {
         $attr = $tag->attributes->getNamedItem('src');
         $filename = "{$this->tempDir}/{$attr->value}";
         $matches = null;
         $found = preg_match('|Stories/Story_(.*)\\.xml|', $attr->value, $matches);
         // u154 <-- Stories/Story_u154.xml
         if ($found == 1) {
             $UID = $matches[1];
             if (!array_key_exists($UID, $this->chaucerHidden)) {
                 //create/store the story if it is not hidden by a designer
                 $story = new IdmlStory($UID);
                 $story->filename = $filename;
                 $this->stories[$UID] = $story;
             }
         } else {
             $this->idmlAssembler->getProgressUpdater()->setWarning("Unable to determine UID for Story '{$attr->value}'.");
         }
     }
     //Parse hyperlink information
     $this->hyperlinks = array();
     $tags = $xpath->query('//Hyperlink');
     $hyperlinkMgr = IdmlHyperlinkManager::getInstance();
     foreach ($tags as $tag) {
         $properties = IdmlParserHelper::getAllDomNodeAttributesAndProperties($tag);
         // This code is (we think) PXE processing code
         if (!array_key_exists($properties['Self'], $this->chaucerHidden)) {
             // create/store the hyperlink if it is not hidden by a designer
             // The $destNode can be either a HyperlinkURLDestination or a HyperlinkPageDestination in the IDML,
             //   and is referenced by the Hyperlink element.
             $destId = $properties['Destination'];
             $destNode = $xpath->query('//*[@Self="' . $destId . '"]');
             if ($destNode->length > 0) {
                 $destNode = $destNode->item(0);
                 $properties['Destination'] = IdmlParserHelper::getAllDomNodeAttributesAndProperties($destNode);
                 $properties['Destination']['DestinationType'] = $destNode->nodeName;
             }
             $this->hyperlinks[$properties['Self']] = $properties;
         }
         // The remainder of this foreach is specifically written for non-PXE IDML
         $hyperlinkSource = $properties['Source'];
         $external = false;
         // unless the link goes to a page outside the epub
         // If the Destination property is an array, the destination is a link to either
         // a page within the epub (with the page UID in the data), or or an external link.
         // So the destination can be set here.
         if (is_array($properties['Destination'])) {
             $anchor = false;
             // link is to a page, not an anchor
             if ($properties['Destination']['DestinationType'] == 'HyperlinkURLDestination') {
                 // External page: use as is
                 $hyperlinkDestination = $properties['Destination']['DestinationURL'];
                 $external = true;
                 // This links to a page outside the epub
             } else {
                 // Internal page. Use the page UID; add the package index and the .html suffix
                 $hyperlinkDestination = $properties['Destination']['DestinationPage'];
             }
         } else {
             $anchor = true;
             // link is to an anchor on a page.
             $hyperlinkDestination = 'Hyperlink_' . $properties['DestinationUniqueKey'];
         }
         $hyperlinkMgr->setSourceDestination($hyperlinkSource, $hyperlinkDestination, $anchor, $external);
     }
     //Parse layer information
     $layers = $xpath->query('//Layer');
     $layerManager = IdmlLayerManager::getInstance();
     foreach ($layers as $layer) {
         $layerManager->addLayer($layer);
     }
     return true;
 }
Пример #4
0
 /**
  * Returns the text frame UID mapped to the specified page UID, for renaming the page in the href attribute
  * @param string $pageUID
  * @return string text frame UID
  */
 public function getDestinationPage($pageUID)
 {
     return IdmlHyperlinkManager::getInstance()->getTextFrameUID($pageUID);
 }
Пример #5
0
 /**
  * Parse DOM.
  * 
  * @param DOMDocument $doc
  */
 private function parse(DOMDocument $doc)
 {
     $xpath = new DOMXPath($doc);
     $q = "//idPkg:{$this->xmlRootName}/{$this->xmlRootName}";
     $nodes = $xpath->query($q);
     $pageNode = $nodes->item(0);
     $attributes = $pageNode->attributes;
     $this->UID = $attributes->getNamedItem('Self')->value;
     $itemTransform = $attributes->getNamedItem('ItemTransform')->value;
     $this->transformation = new IdmlTransformation($itemTransform);
     $this->pageCount = (int) $attributes->getNamedItem('PageCount')->value;
     if ($pageNode->hasAttribute('BindingLocation')) {
         $bindingLocation = (int) $pageNode->getAttribute('BindingLocation');
     } else {
         // this happens with MasterSpreads which do not have a binding location.
         $bindingLocation = -1;
     }
     // First construct the pages (typically one or two pages per spread)
     // although more than two are technically allowed.
     // We need to have pages loaded first.
     $q = "//idPkg:{$this->xmlRootName}/{$this->xmlRootName}//Page";
     $nodes = $xpath->query($q);
     foreach ($nodes as $pageNode) {
         $newPage = new IdmlPage($this);
         $newPage->parse($pageNode);
         $this->pages[] = $newPage;
     }
     // Process children text frames and rectangles.
     $spreadNodes = $doc->getElementsByTagName($this->xmlRootName);
     $spreadNode = $spreadNodes->item(1);
     // Child nodes.
     foreach ($spreadNode->childNodes as $element) {
         $nodeSelf = '';
         if ($element->nodeType == XML_ELEMENT_NODE) {
             /*@var $element DomNode*/
             //get the element's id if possible and make sure it is not to be hidden before we parse it
             $selfIdNode = $element->attributes->getNamedItem('Self');
             if ($selfIdNode) {
                 $nodeSelf = $selfIdNode->nodeValue;
             }
         }
         if ($nodeSelf && array_key_exists($nodeSelf, $this->idmlPackage->chaucerHidden)) {
             error_log('Processing Spread Page, hiding ' . $element->nodeName . ' ' . $nodeSelf . ' ' . __FILE__ . ' Line ' . __LINE__);
         } elseif ($element->nodeType == XML_ELEMENT_NODE) {
             switch ($element->nodeName) {
                 case 'Rectangle':
                     // @TODO - determine whether spans should be used for rectangles parallel to the axes, and code accordingly
                     //                        $rectangle = new IdmlRectangle();
                     $rectangle = new IdmlPolygon();
                     $rectangle->parse($element);
                     $this->dropElementIntoPage($rectangle);
                     break;
                 case 'TextFrame':
                     $newTextFrame = new IdmlTextFrame();
                     $newTextFrame->parse($element);
                     $this->dropElementIntoPage($newTextFrame);
                     $pageUID = $newTextFrame->page != null ? $newTextFrame->page->UID : '000';
                     // And now for some hyperlink management:
                     $hyperlinkMgr = IdmlHyperlinkManager::getInstance();
                     // Update the destination page names for links to anchors.
                     // Refs to the anchors are stored during processing of children, but we don't have the UIDs until the text frame is fully parsed.
                     $hyperlinkMgr->updateDestinationPages($newTextFrame->UID, $pageUID);
                     // Also, map the page UID to the text frame UID so the destination page name can be determined for fixed layout.
                     $hyperlinkMgr->saveTextFrameUID($newTextFrame->UID, $pageUID);
                     break;
                 case 'Group':
                     $group = new IdmlGroup();
                     $group->parse($element);
                     $this->dropElementIntoPage($group);
                     break;
                 case 'Polygon':
                     $polygon = new IdmlPolygon();
                     $polygon->parse($element);
                     $this->dropElementIntoPage($polygon);
                     break;
                 case 'Oval':
                     $oval = new IdmlOval();
                     $oval->parse($element);
                     $this->dropElementIntoPage($oval);
                     break;
                 case 'GraphicLine':
                     $line = new IdmlGraphicLine();
                     $line->parse($element);
                     $this->dropElementIntoPage($line);
                     break;
                 default:
                     // Placeholder: no default action at this time
                     break;
             }
         }
     }
 }
Пример #6
0
 /**
  * Generates the href attribute of the hyperlink
  * @param IdmlHyperlink $element
  * @return string $href - href attribute value
  */
 protected function setHyperlinkHref(IdmlHyperlink $element)
 {
     // Get the destination data from the hyperlink manager
     $hyperlinkMgr = IdmlHyperlinkManager::getInstance();
     $destinationData = $hyperlinkMgr->getSourceDestination($element->contextualStyle->idmlKeyValues['Self']);
     // If the anchor is not set, use the destination in the retrieved data.
     if (!$destinationData['anchor']) {
         $href = $destinationData['destination'];
     } else {
         // $uidArray contains stored page and text frame UIDs; one will be used for the destination filename.
         $uidArray = $hyperlinkMgr->getDestinationPages($destinationData['destination']);
         // $destinationUID contains the appropriate id for fixed (page) or reflowable (text frame);
         // getHyperlinkPage is coded in both fixed and reflowable producers
         $destinationUID = $this->getHyperlinkPage($uidArray);
         // Assemble the full href, using both filename and anchor.
         $href = $destinationUID . '#' . $destinationData['destination'];
     }
     return $href;
 }