File indexing completed on 2025-01-19 05:21:25

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_Search_Lucene
0017  * @subpackage Document
0018  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0019  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0020  * @version    $Id$
0021  */
0022 
0023 /** Zend_Xml_Security */
0024 // require_once 'Zend/Xml/Security.php';
0025 
0026 /** Zend_Search_Lucene_Document_OpenXml */
0027 // require_once 'Zend/Search/Lucene/Document/OpenXml.php';
0028 
0029 /**
0030  * Pptx document.
0031  *
0032  * @category   Zend
0033  * @package    Zend_Search_Lucene
0034  * @subpackage Document
0035  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0036  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0037  */
0038 class Zend_Search_Lucene_Document_Pptx extends Zend_Search_Lucene_Document_OpenXml
0039 {
0040     /**
0041      * Xml Schema - PresentationML
0042      *
0043      * @var string
0044      */
0045     const SCHEMA_PRESENTATIONML = 'http://schemas.openxmlformats.org/presentationml/2006/main';
0046 
0047     /**
0048      * Xml Schema - DrawingML
0049      *
0050      * @var string
0051      */
0052     const SCHEMA_DRAWINGML = 'http://schemas.openxmlformats.org/drawingml/2006/main';
0053 
0054     /**
0055      * Xml Schema - Slide relation
0056      *
0057      * @var string
0058      */
0059     const SCHEMA_SLIDERELATION = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide';
0060 
0061     /**
0062      * Xml Schema - Slide notes relation
0063      *
0064      * @var string
0065      */
0066     const SCHEMA_SLIDENOTESRELATION = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide';
0067 
0068     /**
0069      * Object constructor
0070      *
0071      * @param string  $fileName
0072      * @param boolean $storeContent
0073      * @throws Zend_Search_Lucene_Exception
0074      */
0075     private function __construct($fileName, $storeContent)
0076     {
0077         if (!class_exists('ZipArchive', false)) {
0078             // require_once 'Zend/Search/Lucene/Exception.php';
0079             throw new Zend_Search_Lucene_Exception('MS Office documents processing functionality requires Zip extension to be loaded');
0080         }
0081 
0082         // Document data holders
0083         $slides = array();
0084         $slideNotes = array();
0085         $documentBody = array();
0086         $coreProperties = array();
0087 
0088         // Open OpenXML package
0089         $package = new ZipArchive();
0090         $package->open($fileName);
0091 
0092         // Read relations and search for officeDocument
0093         $relationsXml = $package->getFromName('_rels/.rels');
0094         if ($relationsXml === false) {
0095             // require_once 'Zend/Search/Lucene/Exception.php';
0096             throw new Zend_Search_Lucene_Exception('Invalid archive or corrupted .pptx file.');
0097         }
0098         $relations = Zend_Xml_Security::scan($relationsXml);
0099         foreach ($relations->Relationship as $rel) {
0100             if ($rel["Type"] == Zend_Search_Lucene_Document_OpenXml::SCHEMA_OFFICEDOCUMENT) {
0101                 // Found office document! Search for slides...
0102                 $slideRelations = Zend_Xml_Security::scan($package->getFromName( $this->absoluteZipPath(dirname($rel["Target"]) . "/_rels/" . basename($rel["Target"]) . ".rels")) );
0103                 foreach ($slideRelations->Relationship as $slideRel) {
0104                     if ($slideRel["Type"] == Zend_Search_Lucene_Document_Pptx::SCHEMA_SLIDERELATION) {
0105                         // Found slide!
0106                         $slides[ str_replace( 'rId', '', (string)$slideRel["Id"] ) ] = Zend_Xml_Security::scan(
0107                             $package->getFromName( $this->absoluteZipPath(dirname($rel["Target"]) . "/" . dirname($slideRel["Target"]) . "/" . basename($slideRel["Target"])) )
0108                         );
0109 
0110                         // Search for slide notes
0111                         $slideNotesRelations = Zend_Xml_Security::scan($package->getFromName( $this->absoluteZipPath(dirname($rel["Target"]) . "/" . dirname($slideRel["Target"]) . "/_rels/" . basename($slideRel["Target"]) . ".rels")) );
0112                         foreach ($slideNotesRelations->Relationship as $slideNoteRel) {
0113                             if ($slideNoteRel["Type"] == Zend_Search_Lucene_Document_Pptx::SCHEMA_SLIDENOTESRELATION) {
0114                                 // Found slide notes!
0115                                 $slideNotes[ str_replace( 'rId', '', (string)$slideRel["Id"] ) ] = Zend_Xml_Security::scan(
0116                                     $package->getFromName( $this->absoluteZipPath(dirname($rel["Target"]) . "/" . dirname($slideRel["Target"]) . "/" . dirname($slideNoteRel["Target"]) . "/" . basename($slideNoteRel["Target"])) )
0117                                 );
0118 
0119                                 break;
0120                             }
0121                         }
0122                     }
0123                 }
0124 
0125                 break;
0126             }
0127         }
0128 
0129         // Sort slides
0130         ksort($slides);
0131         ksort($slideNotes);
0132 
0133         // Extract contents from slides
0134         foreach ($slides as $slideKey => $slide) {
0135             // Register namespaces
0136             $slide->registerXPathNamespace("p", Zend_Search_Lucene_Document_Pptx::SCHEMA_PRESENTATIONML);
0137             $slide->registerXPathNamespace("a", Zend_Search_Lucene_Document_Pptx::SCHEMA_DRAWINGML);
0138 
0139             // Fetch all text
0140             $textElements = $slide->xpath('//a:t');
0141             foreach ($textElements as $textElement) {
0142                 $documentBody[] = (string)$textElement;
0143             }
0144 
0145             // Extract contents from slide notes
0146             if (isset($slideNotes[$slideKey])) {
0147                 // Fetch slide note
0148                 $slideNote = $slideNotes[$slideKey];
0149 
0150                 // Register namespaces
0151                 $slideNote->registerXPathNamespace("p", Zend_Search_Lucene_Document_Pptx::SCHEMA_PRESENTATIONML);
0152                 $slideNote->registerXPathNamespace("a", Zend_Search_Lucene_Document_Pptx::SCHEMA_DRAWINGML);
0153 
0154                 // Fetch all text
0155                 $textElements = $slideNote->xpath('//a:t');
0156                 foreach ($textElements as $textElement) {
0157                     $documentBody[] = (string)$textElement;
0158                 }
0159             }
0160         }
0161 
0162         // Read core properties
0163         $coreProperties = $this->extractMetaData($package);
0164 
0165         // Close file
0166         $package->close();
0167 
0168         // Store filename
0169         $this->addField(Zend_Search_Lucene_Field::Text('filename', $fileName, 'UTF-8'));
0170 
0171             // Store contents
0172         if ($storeContent) {
0173             $this->addField(Zend_Search_Lucene_Field::Text('body', implode(' ', $documentBody), 'UTF-8'));
0174         } else {
0175             $this->addField(Zend_Search_Lucene_Field::UnStored('body', implode(' ', $documentBody), 'UTF-8'));
0176         }
0177 
0178         // Store meta data properties
0179         foreach ($coreProperties as $key => $value)
0180         {
0181             $this->addField(Zend_Search_Lucene_Field::Text($key, $value, 'UTF-8'));
0182         }
0183 
0184         // Store title (if not present in meta data)
0185         if (!isset($coreProperties['title']))
0186         {
0187             $this->addField(Zend_Search_Lucene_Field::Text('title', $fileName, 'UTF-8'));
0188         }
0189     }
0190 
0191     /**
0192      * Load Pptx document from a file
0193      *
0194      * @param string  $fileName
0195      * @param boolean $storeContent
0196      * @return Zend_Search_Lucene_Document_Pptx
0197      */
0198     public static function loadPptxFile($fileName, $storeContent = false)
0199     {
0200         return new Zend_Search_Lucene_Document_Pptx($fileName, $storeContent);
0201     }
0202 }