/** * Handles view events for latex files * * @param \Hubzero\Filesystem\Collection $collection The file collection to view * @return void **/ public function onHandleView(\Hubzero\Filesystem\Collection $collection) { if (!$this->canHandle($collection)) { return false; } $file = $collection->findFirstWithExtension('tex'); // Create view $view = new \Hubzero\Plugin\View(['folder' => 'handlers', 'element' => 'latex', 'name' => 'latex', 'layout' => 'view']); // Build path for storing temp previews $outputDir = PATH_APP . DS . trim($this->params->get('compile_dir', 'site/latex/compiled'), DS); $adapter = Manager::adapter('local', ['path' => $outputDir]); $uniqid = md5(uniqid()); $temp = File::fromPath($uniqid . '.tex', $adapter); // Clean up data from Windows characters - important! $data = preg_replace('/[^(\\x20-\\x7F)\\x0A]*/', '', $file->read()); // Store file locally $temp->write($data); // Build the command $command = DS . trim($this->params->get('texpath', '/usr/bin/pdflatex'), DS); $command .= ' -output-directory=' . $outputDir . ' -interaction=batchmode ' . escapeshellarg($temp->getAbsolutePath()); // Exec and capture output exec($command, $out); $compiled = File::fromPath($uniqid . '.pdf', $adapter); $log = File::fromPath($uniqid . '.log', $adapter); if (!$compiled->size()) { $view->setError(Lang::txt('PLG_HANDLERS_LATEX_ERROR_COMPILE_TEX_FAILED')); } // Read log (to show in case of error) if ($log->size()) { $view->log = $log->read(); } $view->compiled = $compiled; return $view; }
/** * 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(); }
/** * Generates the filesystem adapter for the given provider * * @param array $options extra params to include with defaults * @return object **/ public function adapter($options = []) { $params = (array) json_decode($this->params); $params = array_merge($params, $options); return Manager::adapter($this->provider->alias, $params); }