File indexing completed on 2024-12-22 05:33:15
0001 <?php 0002 0003 /** 0004 * ePub Reader class 0005 * 0006 * @package CodeIgniter 0007 * @subpackage Libraries 0008 * @author Tristan Siebers 0009 * @link n/a 0010 * @license LGPL 0011 * @version 0.1.0 0012 */ 0013 class EPubReader 0014 { 0015 /** 0016 * Contains the path to the dir with the ePub files 0017 * 0018 * @var string Path to the extracted ePub files 0019 */ 0020 var $ebookDir; 0021 /** 0022 * Holds the (relative to $ebookDir) path to the OPF file 0023 * 0024 * @var string Location + name of OPF file 0025 */ 0026 var $opfFile; 0027 /** 0028 * Relative (to $ebookDir) OPF (ePub files) dir 0029 * 0030 * @var type Files dir 0031 */ 0032 var $opfDir; 0033 /** 0034 * Holds all the found DC elements in the OPF file 0035 * 0036 * @var array All found DC elements in the OPF file 0037 */ 0038 var $dcElements; 0039 /** 0040 * Holds all the manifest items of the OPF file 0041 * 0042 * @var array All manifest items 0043 */ 0044 var $manifest; 0045 /** 0046 * Holds all the spin data 0047 * 0048 * @var array Spine data 0049 */ 0050 var $spine; 0051 /** 0052 * Holds the ToC data 0053 * 0054 * @var array Array with ToC items 0055 */ 0056 var $toc; 0057 0058 public function init($ebookDir) 0059 { 0060 $this->ebookDir = $ebookDir; 0061 0062 $this->_getOPF(); 0063 $this->_getDcData(); 0064 $this->_getManifest(); 0065 $this->_getSpine(); 0066 $this->_getTOC(); 0067 0068 //$this->debug(); 0069 } 0070 0071 /** 0072 * Get the path to the OPF file from the META-INF/container.xml file 0073 * 0074 * @return string Relative path to the OPF file 0075 */ 0076 private function _getOPF() 0077 { 0078 $opfContents = simplexml_load_file($this->ebookDir . '/META-INF/container.xml'); 0079 $opfAttributes = $opfContents->rootfiles->rootfile->attributes(); 0080 0081 foreach ($opfAttributes as $key => $value) { 0082 if ($key == "full-path") { 0083 $this->opfFile = (string)$value; 0084 } 0085 } 0086 0087 //$this->opfFile = (string) $opfAttributes[0]; // Typecasting to string to get rid of the XML object 0088 0089 // Set also the dir to the OPF (and ePub files) 0090 $opfDirParts = explode('/', $this->opfFile); 0091 unset($opfDirParts[(count($opfDirParts) - 1)]); // remove the last part (it's the .opf file itself) 0092 $this->opfDir = implode('/', $opfDirParts); 0093 0094 return $this->opfFile; 0095 } 0096 0097 /** 0098 * Read the metadata DC details (title, author, etc.) from the OPF file 0099 */ 0100 private function _getDcData() 0101 { 0102 $opfContents = simplexml_load_file($this->ebookDir . '/' . $this->opfFile); 0103 $this->dcElements = (array)$opfContents->metadata->children('dc', true); 0104 } 0105 0106 /** 0107 * Gets the manifest data from the OPF file 0108 */ 0109 private function _getManifest() 0110 { 0111 $opfContents = simplexml_load_file($this->ebookDir . '/' . $this->opfFile); 0112 $iManifest = 0; 0113 foreach ($opfContents->manifest->item as $item) { 0114 $attr = $item->attributes(); 0115 $id = (string)$attr->id; 0116 $this->manifest[$id]['href'] = (string)$attr->href; 0117 $this->manifest[$id]['media-type'] = (string)$attr->{'media-type'}; 0118 $iManifest++; 0119 } 0120 } 0121 0122 /** 0123 * Get the spine data from the OPF file 0124 */ 0125 private function _getSpine() 0126 { 0127 $opfContents = simplexml_load_file($this->ebookDir . '/' . $this->opfFile); 0128 foreach ($opfContents->spine->itemref as $item) { 0129 $attr = $item->attributes(); 0130 $this->spine[] = (string)$attr->idref; 0131 } 0132 } 0133 0134 /** 0135 * Build an array with the TOC 0136 */ 0137 private function _getTOC() 0138 { 0139 $tocFile = $this->getManifest('ncx'); 0140 $tocContents = @simplexml_load_file($this->ebookDir . '/' . $this->opfDir . '/' . $tocFile['href']); 0141 if (!$tocContents) { 0142 return false; 0143 } 0144 0145 $toc = array(); 0146 foreach ($tocContents->navMap->navPoint as $navPoint) { 0147 $toc = $this->_process_navPoint($toc, $navPoint); 0148 } 0149 0150 $this->toc = $toc; 0151 } 0152 0153 /** 0154 * Get the specified manifest item 0155 * 0156 * @param string $item The manifest ID 0157 * 0158 * @return string/boolean String when manifest item exists, otherwise false 0159 */ 0160 public function getManifest($item) 0161 { 0162 if (key_exists($item, $this->manifest)) { 0163 return $this->manifest[$item]; 0164 } else { 0165 return false; 0166 } 0167 } 0168 // Private functions 0169 0170 private function _process_navPoint($toc, $navPoint) 0171 { 0172 $navPointData = $navPoint->attributes(); 0173 $toc[(string)$navPointData['playOrder']]['id'] = (string)$navPointData['id']; 0174 $toc[(string)$navPointData['playOrder']]['name'] = (string)$navPoint->navLabel->text; 0175 $toc[(string)$navPointData['playOrder']]['src'] = (string)$navPoint->content->attributes(); 0176 0177 if ($navPoint->navPoint) { // If there are more navPoints within the current one 0178 foreach ($navPoint->navPoint as $nested_navPoint) { // Process them too 0179 $toc = $this->_process_navPoint($toc, $nested_navPoint); 0180 } 0181 } 0182 0183 return $toc; 0184 } 0185 0186 /** 0187 * Get the specified DC item 0188 * 0189 * @param string $item The DC Item key 0190 * 0191 * @return string/boolean String when DC item exists, otherwise false 0192 */ 0193 public function getDcItem($item) 0194 { 0195 if (key_exists($item, $this->dcElements)) { 0196 return $this->dcElements[$item]; 0197 } else { 0198 return false; 0199 } 0200 } 0201 0202 /** 0203 * Get the specified manifest by type 0204 * 0205 * @param string $type The manifest type 0206 * 0207 * @return string/boolean String when manifest item exists, otherwise false 0208 */ 0209 public function getManifestByType($type) 0210 { 0211 foreach ($this->manifest as $manifestID => $manifest) { 0212 if ($manifest['media-type'] == $type) { 0213 $return[$manifestID]['href'] = $manifest['href']; 0214 $return[$manifestID]['media-type'] = $manifest['media-type']; 0215 } 0216 } 0217 0218 return (count($return) == 0) ? false : $return; 0219 } 0220 0221 /** 0222 * Retrieve the ToC 0223 * 0224 * @return array Array with ToC Data 0225 */ 0226 public function getTOC() 0227 { 0228 return $this->toc; 0229 } 0230 0231 0232 /** 0233 * Build an array with the TOC 0234 * 0235 * private function _getTOC() { 0236 * $tocFile = $this->getManifest('ncx'); 0237 * $tocContents = simplexml_load_file($this->ebookDir.'/'.$this->opfDir.'/'.$tocFile['href']); 0238 * 0239 * $toc = array(); 0240 * foreach($tocContents->navMap->navPoint AS $navPoint) { 0241 * $navPointData = $navPoint->attributes(); 0242 * $toc[(string)$navPointData['playOrder']]['id'] = (string)$navPointData['id']; 0243 * $toc[(string)$navPointData['playOrder']]['naam'] = (string)$navPoint->navLabel->text; 0244 * $toc[(string)$navPointData['playOrder']]['src'] = (string)$navPoint->content->attributes(); 0245 * } 0246 * 0247 * $this->toc = $toc; 0248 * } 0249 */ 0250 0251 /** 0252 * Returns the OPF/Data dir 0253 * 0254 * @return string The OPF/data dir 0255 */ 0256 public function getOPFDir() 0257 { 0258 return $this->opfDir; 0259 } 0260 0261 /* 0262 * Recursive function to get all navPoints, which may be nested 0263 */ 0264 0265 /** 0266 * Prints all contents of the class directly to the screen 0267 */ 0268 public function debug() 0269 { 0270 echo sprintf('<pre>%s</pre>', print_r($this, true)); 0271 } 0272 }