source: pmb4.2/trunk/fuentes/pmb/classes/epubData.class.php @ 815

Last change on this file since 815 was 815, checked in by jrpelegrina, 4 years ago

Initial release of pmb 4.2

  • Property svn:executable set to *
File size: 8.3 KB
Line 
1<?php
2// +-------------------------------------------------+
3// © 2002-2005 PMB Services / www.sigb.net pmb@sigb.net et contributeurs (voir www.sigb.net)
4// +-------------------------------------------------+
5// $Id: epubData.class.php,v 1.3 2013-07-04 12:55:49 arenou Exp $
6
7if (stristr($_SERVER['REQUEST_URI'], ".class.php")) die("no access");
8
9class epubData {
10       
11        var $filename = ''; //Fichier source de l'eBook
12        var $opfFile = ''; //Fichier d'entrée de l'eBook
13        var $opfDir = ''; //Répertoire d'entrée de l'eBook
14        var $metas = array(); //Tableau des métadatas de l'eBook
15        var $items = array(); //Liste des fichiers composant l'eBook
16        var $spine = array(); //Ordre d'affichage des fichiers
17        var $spineToc = ''; //Fichier table des matières
18        var $spinePageMap = ''; //Fichier liste des pages
19        var $pages = array(); //Liste des pages
20        var $toc = array(); //Table des matières
21        var $charset = ''; //Charset de l'epub
22        var $cover_item;        //path vers l'image de couverture
23       
24        //Constructeur
25        public function epubData($filename){
26                if (is_file($filename)){
27                        $this->filename = $filename;
28                        if ($this->isValidEpub()) {
29                                $this->fetchMetadatas();
30                                $this->fetchItems();
31                                $this->fetchSpine();
32                                $this->fetchPages();
33                                $this->fetchToc();
34                        } else {
35                                print ("Fichier eBook non valide : ".$this->filename.".\n");
36                        }
37                } else {
38                        print ("Fichier non trouvé : '".$filename."'.\n");
39                }
40        }
41       
42        //Récupération du contenu texte en vue d'indexation de l'eBook
43        public function getFullTextContent($otherCharset='utf-8') {
44                $chaineRetour = '';
45                foreach ($this->spine as $spinId) {
46                        if ($this->items[$spinId]) {
47                                $contents = html_entity_decode($this->getContentFile($this->opfDir.$this->items[$spinId]["href"]));
48                        }                       
49                        $chaineRetour .= strip_tags($contents);                 
50                }
51                if ($otherCharset != "utf-8") {
52                        $chaineRetour = utf8_decode($chaineRetour);
53                }
54                return $chaineRetour;
55        }
56       
57        //Récupération du contenu d'une page
58        public function getPageContent($page) {
59                $chaineRetour = $this->getContentFile($this->opfDir.$page);
60                if (!preg_match('`meta charset`',$chaineRetour)) {
61                        $chaineRetour = str_replace("<head>","<head><meta charset=\"UTF-8\">",$chaineRetour);
62                }
63                return $chaineRetour;
64        }
65       
66        private function isValidEpub() {
67                $isValid = true;
68                //On vérifie le fichier "mimetype" et son contenu
69                $mime = $this->getContentFile("mimetype");
70                if (!preg_match('(application\/epub\+zip)', $mime)) {
71                        $isValid = false;
72                }
73                return $isValid;
74        }
75       
76        //Récupération des métadatas
77        private function fetchMetadatas() {
78                //On ouvre le container.xml
79                $contents = $this->getContentFile("META-INF/container.xml");
80                if (trim($contents)) {
81                        $xml = simplexml_load_string($contents);
82                        //On va chercher le fichier opf
83                        $tmpFile = $this->decodeCharset($xml->rootfiles->rootfile->attributes()->{'full-path'});
84                        $tmpArray = explode("/",$tmpFile);
85                        $this->opfFile =array_pop($tmpArray);
86                        $this->opfDir = implode("/",$tmpArray)."/";
87                        $contents = $this->getContentFile($this->opfDir.$this->opfFile);
88                        //On cherche le charset
89                        $this->charset = strtolower(mb_detect_encoding($contents));
90                        $xml = simplexml_load_string($contents);               
91                        //on déclare les namespaces
92                        $namespaces = $xml->getNamespaces(true);
93                        foreach ($namespaces as $k=>$v) {
94                                if (trim($k)) {
95                                        define(strtoupper($k), $v);
96                                }
97                        }
98                        //on va chercher les metas
99                        $xmlMeta = $xml->children(OPF, false)->metadata->children(DC, false);
100                        foreach ($xmlMeta as $k=>$v) {
101                                $key = $this->decodeCharset($k);
102                                switch($key){
103                                        case "creator":
104                                        case "contributor":
105                                        case "date" :   
106                                                $aut = array();
107                                                foreach($v->attributes(OPF,false) as $k_attr => $v_attr){
108                                                        $aut[strtolower($this->decodeCharset($k_attr))]=$this->decodeCharset($v_attr);
109                                                }
110                                                $aut['value'] = $this->decodeCharset($v);
111                                                $this->metas[$this->decodeCharset($k)][]=$aut;
112                                                break;
113                                        case "identifier":
114                                                $attrs = $v->attributes(OPF,false);
115                                                foreach($attrs as $k_attr => $v_attr){
116                                                        $this->metas[$this->decodeCharset($k)][strtolower($this->decodeCharset($v_attr))]=$this->decodeCharset($v);
117                                                }
118                                                //le cas où la norme est bien loin...
119                                                if(!$this->metas[$this->decodeCharset($k)]){
120                                                        $this->metas[$this->decodeCharset($k)]['value'] = $this->decodeCharset($v);
121                                                }
122                                                break;
123                                        default :
124                                                $this->metas[$this->decodeCharset($k)][] = $this->decodeCharset($v);
125                                                break;
126                                }
127                        }
128                        //on regarde si on a une mage de couverture...
129                        $metastag = $xml->children(OPF, false)->metadata->children(OPF,false);
130                        $this->cover_item ="";
131                        foreach ($metastag as $k=>$v) {
132                                $key = $this->decodeCharset($k);
133                                if($key != "meta"){
134                                        continue;
135                                }
136                                $attrs = $v->attributes();
137                                if($attrs->{"name"} == "cover") {
138                                        $this->cover_item = $this->decodeCharset($attrs->{"content"});
139                                        break;
140                                }
141                        }
142                       
143                }
144        }
145       
146        //Récupération des items de l'eBook
147        private function fetchItems() {
148                $contents = $this->getContentFile($this->opfDir.$this->opfFile);
149                if (trim($contents)) {
150                        $xml = simplexml_load_string($contents);
151                        foreach ($xml->manifest->item as $item) {
152                                $this->items[$this->decodeCharset($item->attributes()->{'id'})]["href"] =  $this->decodeCharset($item->attributes()->{'href'});
153                                $this->items[$this->decodeCharset($item->attributes()->{'id'})]["media-type"] =  $this->decodeCharset($item->attributes()->{'media-type'});
154                        }
155                }
156        }
157       
158        //Récupération de l'ordre d'affichage des fichiers
159        private function fetchSpine() {
160                $contents = $this->getContentFile($this->opfDir.$this->opfFile);
161                if (trim($contents)) {
162                        $xml = simplexml_load_string($contents);
163                        $this->spineToc = $this->decodeCharset($xml->spine->attributes()->{'toc'});
164                        $this->spinePageMap = $this->decodeCharset($xml->spine->attributes()->{'page-map'});
165                        foreach ($xml->spine->itemref as $item) {
166                                $this->spine[] =  $this->decodeCharset($item->attributes()->{'idref'});
167                        }
168                }
169        }
170       
171        //Récupération des pages de l'eBook
172        private function fetchPages() {
173                $contents = $this->getContentFile($this->opfDir.$this->items[$this->spinePageMap]["href"]);
174                if (trim($contents)) {
175                        $xml = simplexml_load_string($contents);
176                        foreach ($xml->page as $item) {
177                                $tmpArray = array();
178                                $tmpArray['name'] = $this->decodeCharset($item->attributes()->{'name'});
179                                $tmpArray['href'] = $this->decodeCharset($item->attributes()->{'href'});
180                                $this->pages[] = $tmpArray;
181                        }
182                } else {
183                        //Pafois nous n'avons pas de liste des pages
184                        foreach ($this->items as $item) {
185                                if ($item["media-type"]=='application/xhtml+xml') {
186                                        $tmpArray = array();
187                                        $tmpArray['name'] = $item["href"];
188                                        $tmpArray['href'] = $item["href"];
189                                        $this->pages[] = $tmpArray;
190                                }
191                        }
192                }
193        }
194       
195        //Récupération de la table des matières
196        private function fetchToc() {
197                $contents = $this->getContentFile($this->opfDir.$this->items[$this->spineToc]["href"]);
198                        if (trim($contents)) {
199                        $xml = simplexml_load_string($contents);
200                        foreach ($xml->navMap->navPoint as $item) {
201                                $this->readNavPoint($item,0);
202                        }
203                }
204        }
205       
206        //méthode pour retrouver de façon récurrente les points de navigation
207        private function readNavPoint($simpleXmlObject,$level){
208                $tmpArray = array();
209                $tmpArray['playOrder'] = $this->decodeCharset($simpleXmlObject->attributes()->{'playOrder'});
210                $tmpArray['text'] = $this->decodeCharset($simpleXmlObject->navLabel->text);
211                $tmpArray['content'] = $this->decodeCharset($simpleXmlObject->content->attributes()->{'src'});
212                $tmpArray['level'] = $level;
213                $this->toc[] = $tmpArray;
214                $level++;
215                foreach ($simpleXmlObject->navPoint as $item) {
216                        $this->readNavPoint($item,$level);
217                }
218        }
219       
220        //On va chercher le contenu d'un fichier de l'archive eBook
221        private function getContentFile($file){
222                //On essaye de gagner du temps pour l'affichage dans la visionneuse
223                session_write_close();
224                $zip = zip_open($this->filename);
225                $contents = "";
226                if ($zip) {
227                        while ($zip_entry = zip_read($zip)) {
228                                if(zip_entry_name($zip_entry) == $file && zip_entry_open($zip, $zip_entry))     {
229                                        $contents = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
230                                        zip_entry_close($zip_entry);
231                                }
232                        }
233                        zip_close($zip);
234                        return $contents;
235                }
236        }
237       
238        //Fonction de décodage selon l'environnement
239        private function decodeCharset($string) {               
240                $string = htmlentities($string,ENT_QUOTES,$this->charset);
241                return $string;
242        }
243       
244        //Pour la route...
245        public function getCoverContent(){
246                return $this->getContentFile($this->opfDir.$this->items[$this->cover_item]['href']);
247        }
248}
249?>
Note: See TracBrowser for help on using the repository browser.