예제 #1
0
 /**
  * Compile PDF/image preview for any kind of file
  *
  *
  * @return  mixed  array or false
  */
 protected function _compile()
 {
     // Combine file and folder data
     $items = $this->_sortIncoming();
     // Get stored remote connections
     $remotes = $this->_getRemoteConnections();
     // Params for repo call
     $params = array('subdir' => $this->subdir, 'remoteConnections' => $remotes);
     // Incoming
     $commit = Request::getInt('commit', 0);
     $download = Request::getInt('download', 0);
     // Check that we have compile enabled
     if (!$this->params->get('latex')) {
         $this->setError(Lang::txt('PLG_PROJECTS_FILES_COMPILE_NOTALLOWED'));
         return;
     }
     // Output HTML
     $view = new \Hubzero\Plugin\View(array('folder' => 'projects', 'element' => 'files', 'name' => 'compiled'));
     // Get selected item
     if (!$items) {
         $view->setError(Lang::txt('PLG_PROJECTS_FILES_ERROR_NO_FILES_TO_COMPILE'));
         $view->loadTemplate();
         return;
     } else {
         foreach ($items as $element) {
             foreach ($element as $type => $item) {
                 // Get our metadata
                 $file = $this->repo->getMetadata($item, 'file', $params);
                 break;
             }
         }
     }
     // We need a file
     if (empty($file)) {
         $view->setError(Lang::txt('PLG_PROJECTS_FILES_ERROR_NO_FILES_TO_COMPILE'));
         $view->loadTemplate();
         return;
     }
     // Path for storing temp previews
     $imagePath = trim($this->model->config()->get('imagepath', '/site/projects'), DS);
     $outputDir = DS . $imagePath . DS . strtolower($this->model->get('alias')) . DS . 'compiled';
     // Make sure output dir exists
     if (!is_dir(PATH_APP . $outputDir)) {
         if (!Filesystem::makeDirectory(PATH_APP . $outputDir)) {
             $this->setError(Lang::txt('PLG_PROJECTS_FILES_UNABLE_TO_CREATE_UPLOAD_PATH'));
             return;
         }
     }
     // Get LaTeX helper
     $compiler = new \Components\Projects\Helpers\Compiler();
     // Tex compiler path
     $texPath = DS . trim($this->params->get('texpath'), DS);
     $view->file = $file;
     $view->oWidth = '780';
     $view->oHeight = '460';
     $view->url = Route::url($this->model->link('files'));
     $cExt = 'pdf';
     // Take out Google native extension if present
     $fileName = $file->get('name');
     if (in_array($file->get('ext'), \Components\Projects\Helpers\Google::getGoogleNativeExts())) {
         $fileName = preg_replace("/." . $file->get('ext') . "\\z/", "", $file->get('name'));
     }
     // Tex file?
     $tex = $compiler->isTexFile($fileName);
     // Build temp name
     $tempBase = $tex ? 'temp__' . \Components\Projects\Helpers\Html::takeOutExt($fileName) : $fileName;
     $tempBase = str_replace(' ', '_', $tempBase);
     // Get file contents
     if (!empty($this->_remoteService) && $file->get('converted')) {
         // Load remote resource
         $this->_connect->setUser($this->model->get('owned_by_user'));
         $resource = $this->_connect->loadRemoteResource($this->_remoteService, $this->model->get('owned_by_user'), $file->get('remoteId'));
         $cExt = $tex ? 'tex' : \Components\Projects\Helpers\Google::getGoogleImportExt($resource['mimeType']);
         $cExt = in_array($cExt, array('tex', 'jpeg')) ? $cExt : 'pdf';
         $url = \Components\Projects\Helpers\Google::getDownloadUrl($resource, $cExt);
         // Get data
         $view->data = $this->_connect->sendHttpRequest($this->_remoteService, $this->model->get('owned_by_user'), $url);
     } elseif ($file->exists()) {
         $view->data = $file->isImage() ? NULL : $file->contents();
     } else {
         $this->setError(Lang::txt('PLG_PROJECTS_FILES_ERROR_COMPILE_NO_DATA'));
     }
     // LaTeX file?
     if ($tex && !empty($view->data)) {
         // Clean up data from Windows characters - important!
         $view->data = preg_replace('/[^(\\x20-\\x7F)\\x0A]*/', '', $view->data);
         // Compile and get path to PDF
         $contentFile = $compiler->compileTex($file->get('fullPath'), $view->data, $texPath, PATH_APP . $outputDir, 1, $tempBase);
         // Read log (to show in case of error)
         $logFile = $tempBase . '.log';
         if (file_exists(PATH_APP . $outputDir . DS . $logFile)) {
             $view->log = Filesystem::read(PATH_APP . $outputDir . DS . $logFile);
         }
         if (!$contentFile) {
             $this->setError(Lang::txt('PLG_PROJECTS_FILES_ERROR_COMPILE_TEX_FAILED'));
         }
     } elseif ($file->get('converted') && !empty($view->data)) {
         $tempBase = \Components\Projects\Helpers\Google::getImportFilename($file->get('name'), $cExt);
         // Write content to temp file
         $this->_connect->fetchFile($view->data, $tempBase, PATH_APP . $outputDir);
         $contentFile = $tempBase;
     } elseif (!$this->getError()) {
         // Make sure we can handle preview of this type of file
         if ($file->get('ext') == 'pdf' || $file->isImage() || !$file->isBinary()) {
             Filesystem::copy($file->get('fullPath'), PATH_APP . $outputDir . DS . $tempBase);
             $contentFile = $tempBase;
         }
     }
     $url = $this->model->link('files');
     $url .= $this->repo->isLocal() ? '' : '&repo=' . $this->repo->get('name');
     $url .= $this->subdir ? '&subdir=' . urlencode($this->subdir) : '';
     // Parse output
     if (!empty($contentFile) && file_exists(PATH_APP . $outputDir . DS . $contentFile)) {
         // Get compiled content mimetype
         $cType = Filesystem::mimetype(PATH_APP . $outputDir . DS . $contentFile);
         // Is image?
         if (strpos($cType, 'image/') !== false) {
             // Fix up object width & height
             list($width, $height, $type, $attr) = getimagesize(PATH_APP . $outputDir . DS . $contentFile);
             $xRatio = $view->oWidth / $width;
             $yRatio = $view->oHeight / $height;
             if ($xRatio * $height < $view->oHeight) {
                 // Resize the image based on width
                 $view->oHeight = ceil($xRatio * $height);
             } else {
                 // Resize the image based on height
                 $view->oWidth = ceil($yRatio * $width);
             }
         }
         // Download compiled file?
         if ($download) {
             $pdfName = $tex ? str_replace('temp__', '', basename($contentFile)) : basename($contentFile);
             // Serve up file
             $server = new \Hubzero\Content\Server();
             $server->filename(PATH_APP . $outputDir . DS . $contentFile);
             $server->disposition('attachment');
             $server->acceptranges(false);
             $server->saveas($pdfName);
             $result = $server->serve_attachment(PATH_APP . $outputDir . DS . $contentFile, $pdfName, false);
             if (!$result) {
                 // Should only get here on error
                 App::abort(404, Lang::txt('PLG_PROJECTS_FILES_SERVER_ERROR'));
             } else {
                 exit;
             }
         }
         // Add compiled PDF to repository?
         if ($commit && $tex) {
             $pdfName = str_replace('temp__', '', basename($contentFile));
             $where = $this->subdir ? $this->subdir . DS . $pdfName : $pdfName;
             if (Filesystem::copy(PATH_APP . $outputDir . DS . $contentFile, $this->_path . DS . $where)) {
                 // Checkin into repo
                 $params = array('subdir' => $this->subdir);
                 $params['file'] = $this->repo->getMetadata($pdfName, 'file', $params);
                 $this->repo->call('checkin', $params);
                 if ($this->repo->isLocal()) {
                     $this->model->saveParam('google_sync_queue', 1);
                 }
                 \Notify::message(Lang::txt('PLG_PROJECTS_FILES_SUCCESS_COMPILED'), 'success', 'projects');
                 // Redirect to file list
                 App::redirect(Route::url($url));
                 return;
             }
         }
         // Generate preview image for browsers that cannot embed pdf
         if ($cType == 'application/pdf') {
             // GS path
             $gspath = trim($this->params->get('gspath'), DS);
             if ($gspath && file_exists(DS . $gspath . DS . 'gs')) {
                 $gspath = DS . $gspath . DS;
                 $pdfName = $tex ? str_replace('temp__', '', basename($contentFile)) : basename($contentFile);
                 $pdfPath = PATH_APP . $outputDir . DS . $contentFile;
                 $exportPath = PATH_APP . $outputDir . DS . $tempBase . '%d.jpg';
                 exec($gspath . "gs -dNOPAUSE -sDEVICE=jpeg -r300 -dFirstPage=1 -dLastPage=1 -sOutputFile={$exportPath} {$pdfPath} 2>&1", $out);
                 if (is_file(PATH_APP . $outputDir . DS . $tempBase . '1.jpg')) {
                     $hi = new \Hubzero\Image\Processor(PATH_APP . $outputDir . DS . $tempBase . '1.jpg');
                     if (count($hi->getErrors()) == 0) {
                         $hi->resize($view->oWidth, false, false, true);
                         $hi->save(PATH_APP . $outputDir . DS . $tempBase . '1.jpg');
                     } else {
                         return false;
                     }
                 }
                 if (is_file(PATH_APP . $outputDir . DS . $tempBase . '1.jpg')) {
                     $image = $tempBase . '1.jpg';
                 }
             }
         }
     } elseif (!$this->getError()) {
         $this->setError(Lang::txt('PLG_PROJECTS_FILES_ERROR_COMPILE_PREVIEW_FAILED'));
     }
     $view->file = $file;
     $view->outputDir = $outputDir;
     $view->embed = $contentFile;
     $view->cType = $cType;
     $view->subdir = $this->subdir;
     $view->option = $this->_option;
     $view->image = !empty($image) ? $image : NULL;
     $view->model = $this->model;
     $view->repo = $this->repo;
     if ($this->getError()) {
         $view->setError($this->getError());
     }
     return $view->loadTemplate();
 }
예제 #2
0
 /**
  * Compiles PDF/image preview for any kind of file
  *
  * @return  string
  */
 public function compile()
 {
     // Combine file and folder data
     $items = $this->getCollection();
     // Incoming
     $download = Request::getInt('download', 0);
     // Check that we have compile enabled
     // @FIXME: why are latex and compiled preview tied together?
     //         presumedly we are also 'compiling' pdfs?
     if (!$this->params->get('latex')) {
         $this->setError(Lang::txt('PLG_PROJECTS_FILES_COMPILE_NOTALLOWED'));
         return;
     }
     // Output HTML
     $view = new \Hubzero\Plugin\View(['folder' => 'projects', 'element' => 'files', 'name' => 'connected', 'layout' => 'compiled']);
     // Make sure we have an item
     if (count($items) == 0) {
         $view->setError(Lang::txt('PLG_PROJECTS_FILES_ERROR_NO_FILES_TO_COMPILE'));
         $view->loadTemplate();
         return;
     }
     // We can only handle one file at a time
     $file = $items->first();
     // Build path for storing temp previews
     $imagePath = trim($this->model->config()->get('imagepath', '/site/projects'), DS);
     $outputDir = DS . $imagePath . DS . strtolower($this->model->get('alias')) . DS . 'compiled';
     // Make sure output dir exists
     if (!is_dir(PATH_APP . $outputDir)) {
         if (!Filesystem::makeDirectory(PATH_APP . $outputDir)) {
             $this->setError(Lang::txt('PLG_PROJECTS_FILES_UNABLE_TO_CREATE_UPLOAD_PATH'));
             return;
         }
     }
     // Get LaTeX helper
     $compiler = new \Components\Projects\Helpers\Compiler();
     // Tex compiler path
     $texPath = DS . trim($this->params->get('texpath'), DS);
     // Set view args and defaults
     $view->file = $file;
     $view->oWidth = '780';
     $view->oHeight = '460';
     $view->url = $this->model->link('files');
     $cExt = 'pdf';
     // Tex file?
     $tex = $compiler->isTexFile($file->getName());
     // Build temp name
     $tempBase = $tex ? 'temp__' . \Components\Projects\Helpers\Html::takeOutExt($file->getName()) : $file->getName();
     $tempBase = str_replace(' ', '_', $tempBase);
     $view->data = $file->isImage() ? NULL : $file->read();
     // LaTeX file?
     if ($tex && !empty($view->data)) {
         // Clean up data from Windows characters - important!
         $view->data = preg_replace('/[^(\\x20-\\x7F)\\x0A]*/', '', $view->data);
         // Store file locally
         $tmpfile = PATH_APP . $outputDir . DS . $tempBase;
         file_put_contents($tmpfile, $view->data);
         // Compile and get path to PDF
         $contentFile = $compiler->compileTex($tmpfile, $view->data, $texPath, PATH_APP . $outputDir, 1, $tempBase);
         // Read log (to show in case of error)
         $logFile = $tempBase . '.log';
         if (file_exists(PATH_APP . $outputDir . DS . $logFile)) {
             $view->log = Filesystem::read(PATH_APP . $outputDir . DS . $logFile);
         }
         if (!$contentFile) {
             $this->setError(Lang::txt('PLG_PROJECTS_FILES_ERROR_COMPILE_TEX_FAILED'));
         }
         $cType = Filesystem::mimetype(PATH_APP . $outputDir . DS . $contentFile);
     } else {
         // Make sure we can handle preview of this type of file
         if ($file->hasExtension('pdf') || $file->isImage() || !$file->isBinary()) {
             $origin = $this->connection->provider->alias . '://' . $file->getPath();
             $dest = 'compiled://' . $tempBase;
             // Do the copy
             Manager::adapter('local', ['path' => PATH_APP . $outputDir . DS], 'compiled');
             Manager::copy($origin, $dest);
             $contentFile = $tempBase;
         }
     }
     // Parse output
     if (!empty($contentFile) && file_exists(PATH_APP . $outputDir . DS . $contentFile)) {
         // Get compiled content mimetype
         $cType = Filesystem::mimetype(PATH_APP . $outputDir . DS . $contentFile);
         // Is image?
         if (strpos($cType, 'image/') !== false) {
             // Fix up object width & height
             list($width, $height, $type, $attr) = getimagesize(PATH_APP . $outputDir . DS . $contentFile);
             $xRatio = $view->oWidth / $width;
             $yRatio = $view->oHeight / $height;
             if ($xRatio * $height < $view->oHeight) {
                 // Resize the image based on width
                 $view->oHeight = ceil($xRatio * $height);
             } else {
                 // Resize the image based on height
                 $view->oWidth = ceil($yRatio * $width);
             }
         }
         // Download compiled file?
         if ($download) {
             $pdfName = $tex ? str_replace('temp__', '', basename($contentFile)) : basename($contentFile);
             // Serve up file
             $server = new \Hubzero\Content\Server();
             $server->filename(PATH_APP . $outputDir . DS . $contentFile);
             $server->disposition('attachment');
             $server->acceptranges(false);
             $server->saveas($pdfName);
             $result = $server->serve();
             if (!$result) {
                 // Should only get here on error
                 throw new Exception(Lang::txt('PLG_PROJECTS_FILES_SERVER_ERROR'), 404);
             } else {
                 exit;
             }
         }
         // Generate preview image for browsers that cannot embed pdf
         if ($cType == 'application/pdf') {
             // GS path
             $gspath = trim($this->params->get('gspath'), DS);
             if ($gspath && file_exists(DS . $gspath . DS . 'gs')) {
                 $gspath = DS . $gspath . DS;
                 $pdfName = $tex ? str_replace('temp__', '', basename($contentFile)) : basename($contentFile);
                 $pdfPath = PATH_APP . $outputDir . DS . $contentFile;
                 $exportPath = PATH_APP . $outputDir . DS . $tempBase . '%d.jpg';
                 exec($gspath . "gs -dNOPAUSE -sDEVICE=jpeg -r300 -dFirstPage=1 -dLastPage=1 -sOutputFile={$exportPath} {$pdfPath} 2>&1", $out);
                 if (is_file(PATH_APP . $outputDir . DS . $tempBase . '1.jpg')) {
                     $hi = new \Hubzero\Image\Processor(PATH_APP . $outputDir . DS . $tempBase . '1.jpg');
                     if (count($hi->getErrors()) == 0) {
                         $hi->resize($view->oWidth, false, false, true);
                         $hi->save(PATH_APP . $outputDir . DS . $tempBase . '1.jpg');
                     } else {
                         return false;
                     }
                 }
                 if (is_file(PATH_APP . $outputDir . DS . $tempBase . '1.jpg')) {
                     $image = $tempBase . '1.jpg';
                 }
             }
         }
     } elseif (!$this->getError()) {
         $this->setError(Lang::txt('PLG_PROJECTS_FILES_ERROR_COMPILE_PREVIEW_FAILED'));
     }
     $view->file = $file;
     $view->outputDir = $outputDir;
     $view->embed = $contentFile;
     $view->cType = $cType;
     $view->subdir = $this->subdir;
     $view->option = $this->_option;
     $view->image = !empty($image) ? $image : NULL;
     $view->model = $this->model;
     $view->repo = $this->repo;
     $view->connection = $this->connection;
     if ($this->getError()) {
         $view->setError($this->getError());
     }
     return $view->loadTemplate();
 }
예제 #3
0
 /**
  * Set mime type
  *
  * @return  mixed
  */
 public function setMimeType()
 {
     if (!$this->get('mimeType')) {
         $this->set('mimeType', Filesystem::mimetype($this->get('fullPath')));
     }
 }
예제 #4
0
 /**
  * Get changes for sync
  *
  * @return     array
  */
 public function getChanges($localPath = '', $synced = '', $localDir = '', &$localRenames, $connections)
 {
     // Collector array
     $locals = array();
     // Initial sync
     if ($synced == 1) {
         $files = $this->callGit('ls-files --full-name ' . escapeshellarg($localDir));
         $files = empty($files) || substr($files[0], 0, 5) == 'fatal' ? array() : $files;
         if (empty($files)) {
             return $locals;
         }
         foreach ($files as $filename) {
             $type = 'file';
             // We are only interested in last local change on the file
             if (!isset($locals[$filename])) {
                 $time = strtotime(date('c', time()));
                 // Important! needs to be local time, NOT UTC
                 $locals[$filename] = array('status' => 'A', 'time' => $time, 'type' => $type, 'remoteid' => 0, 'converted' => 0, 'rParent' => NULL, 'local_path' => $filename, 'title' => basename($filename), 'author' => NULL, 'modified' => gmdate('Y-m-d H:i:s', $time), 'synced' => NULL, 'fullPath' => $localPath . DS . $filename, 'mimeType' => Filesystem::mimetype($localPath . DS . $filename), 'md5' => NULL, 'rename' => NULL);
             }
         }
     } else {
         // Collect
         $since = $synced != 1 ? ' --since="' . $synced . '"' : '';
         $where = $localDir ? '  --all -- ' . escapeshellarg($localDir) . ' ' : ' --all ';
         $changes = $this->callGit('rev-list ' . $where . $since);
         // Empty repo or no changes?
         if (empty($changes) || trim(substr($changes[0], 0, 5)) == 'usage') {
             $changes = array();
         }
         // Parse Git file list to find which items changed since last sync
         if (count($changes) > 0) {
             $timestamps = array();
             // Get files involved in each commit
             foreach ($changes as $hash) {
                 // Get time and author of commit
                 $time = $this->gitLog('', $hash, 'timestamp');
                 $author = $this->gitLog('', $hash, 'author');
                 // Get filename and change
                 $fileinfo = $this->callGit('diff --name-status ' . $hash . '^ ' . $hash);
                 // First commit
                 if (!empty($fileinfo) && !empty($fileinfo[0]) && substr($fileinfo[0], 0, 5) == 'fatal') {
                     $fileinfo = $this->callGit('log --pretty=oneline --name-status --root');
                     if (!empty($fileinfo)) {
                         // Remove first line
                         array_shift($fileinfo);
                     }
                 }
                 if (empty($fileinfo)) {
                     continue;
                 }
                 // Go through files
                 foreach ($fileinfo as $line) {
                     $n = substr($line, 0, 1);
                     if ($n == 'f') {
                         // First file in repository
                         $finfo = $this->callGit('log --pretty=oneline --name-status ' . $hash);
                         $status = 'A';
                         $filename = trim(substr($finfo[1], 1));
                         break;
                     } else {
                         $status = $n;
                         $filename = trim(substr($line, 1));
                     }
                     $type = 'file';
                     $rename = '';
                     // Detect a rename
                     if (isset($localRenames[$filename])) {
                         $rename = $localRenames[$filename];
                     } else {
                         $rename = $this->getRename($filename, $hash, $since);
                         if ($rename && $status == 'A') {
                             // Rename or move?
                             if (basename($rename) == basename($filename)) {
                                 $status = 'W';
                                 // this means 'move'
                             } else {
                                 $status = 'R';
                             }
                             $localRenames[$filename] = $rename;
                         }
                     }
                     // Hidden file in local directory - treat as directory
                     if (preg_match("/.gitignore/", $filename)) {
                         $filename = dirname($filename);
                         // Skip home directory
                         if ($filename == '.') {
                             continue;
                         }
                         $type = 'folder';
                     }
                     // Specific local directory is synced?
                     $lFilename = $localDir ? preg_replace("/^" . $localDir . "\\//", "", $filename) : $filename;
                     $conn = isset($connections['paths']) ? $connections['paths'] : NULL;
                     $search = $status == 'R' || $status == 'W' ? $rename : $filename;
                     $found = isset($conn[$search]) && $conn[$search]['type'] == $type ? $conn[$search] : false;
                     // Rename/move connection not found  - check against new name in case of repeat sync
                     if (!$found && ($status == 'R' || $status == 'W')) {
                         $found = isset($conn[$filename]) && $conn[$filename]['type'] == $type ? $conn[$filename] : false;
                     }
                     $remoteid = $found ? $found['remote_id'] : NULL;
                     $converted = $found ? $found['converted'] : 0;
                     $rParent = $found ? $found['rParent'] : NULL;
                     $syncT = $found ? $found['synced'] : NULL;
                     $md5Checksum = $type == 'file' && file_exists($localPath . DS . $filename) ? hash_file('md5', $localPath . DS . $filename) : NULL;
                     $mimeType = $type == 'file' ? Filesystem::mimetype($localPath . DS . $filename) : NULL;
                     // We are only interested in last local change on the file
                     if (!isset($locals[$lFilename])) {
                         $locals[$lFilename] = array('status' => $status, 'time' => $time, 'type' => $type, 'remoteid' => $remoteid, 'converted' => $converted, 'rParent' => $rParent, 'local_path' => $filename, 'title' => basename($filename), 'author' => $author, 'modified' => gmdate('Y-m-d H:i:s', $time), 'synced' => $syncT, 'fullPath' => $localPath . DS . $filename, 'mimeType' => $mimeType, 'md5' => $md5Checksum, 'rename' => $rename);
                         $timestamps[] = $time;
                     }
                 }
             }
             // Sort by time, most recent first
             //array_multisort($timestamps, SORT_DESC, $locals, SORT_STRING);
         }
     }
     return $locals;
 }