%PDF- %PDF-
| Direktori : /www/varak.net/mail2.varak.net_old/libraries/Knp/Snappy/ |
| Current File : /www/varak.net/mail2.varak.net_old/libraries/Knp/Snappy/AbstractGenerator.php |
<?php
namespace Knp\Snappy;
use Knp\Snappy\Exception as Exceptions;
/**
* Base generator class for medias
*
* @package Snappy
*
* @author Matthieu Bontemps <matthieu.bontemps@knplabs.com>
* @author Antoine Hérault <antoine.herault@knplabs.com>
*/
abstract class AbstractGenerator implements GeneratorInterface
{
private $binary;
private $options = array();
private $env;
private $timeout = false;
private $defaultExtension;
/**
* Constructor
*
* @param string $binary
* @param array $options
*/
public function __construct($binary, array $options = array(), array $env = null)
{
$this->configure();
$this->setBinary($binary);
$this->setOptions($options);
$this->env = $env;
}
/**
* This method must configure the media options
*
* @see AbstractGenerator::addOption()
*/
abstract protected function configure();
/**
* Sets the default extension.
* Useful when letting Snappy deal with file creation
*
* @param string $defaultExtension
*/
public function setDefaultExtension($defaultExtension)
{
$this->defaultExtension = $defaultExtension;
}
/**
* Gets the default extension
*
* @return $string
*/
public function getDefaultExtension()
{
return $this->defaultExtension;
}
/**
* Sets an option. Be aware that option values are NOT validated and that
* it is your responsibility to validate user inputs
*
* @param string $name The option to set
* @param mixed $value The value (NULL to unset)
*/
public function setOption($name, $value)
{
if (!array_key_exists($name, $this->options)) {
throw new \InvalidArgumentException(sprintf('The option \'%s\' does not exist.', $name));
}
$this->options[$name] = $value;
}
/**
* Sets the timeout. Be aware that option only works with symfony
*
* @param integer $timeout The timeout to set
*/
public function setTimeout($timeout)
{
$this->timeout = $timeout;
}
/**
* Sets an array of options
*
* @param array $options An associative array of options as name/value
*/
public function setOptions(array $options)
{
foreach ($options as $name => $value) {
$this->setOption($name, $value);
}
}
/**
* Returns all the options
*
* @return array
*/
public function getOptions()
{
return $this->options;
}
/**
* {@inheritDoc}
*/
public function generate($input, $output, array $options = array(), $overwrite = false)
{
if (null === $this->binary) {
throw new \LogicException(
'You must define a binary prior to conversion.'
);
}
$this->prepareOutput($output, $overwrite);
$command = $this->getCommand($input, $output, $options);
list($status, $stdout, $stderr) = $this->executeCommand($command);
$this->checkProcessStatus($status, $stdout, $stderr, $command);
$this->checkOutput($output, $command);
}
/**
* {@inheritDoc}
*/
public function generateFromHtml($html, $output, array $options = array(), $overwrite = false)
{
$filename = $this->createTemporaryFile($html, 'html');
$this->generate($filename, $output, $options, $overwrite);
$this->unlink($filename);
}
/**
* {@inheritDoc}
*/
public function getOutput($input, array $options = array())
{
$filename = $this->createTemporaryFile(null, $this->getDefaultExtension());
$this->generate($input, $filename, $options);
$result = $this->getFileContents($filename);
$this->unlink($filename);
return $result;
}
/**
* {@inheritDoc}
*/
public function getOutputFromHtml($html, array $options = array())
{
$filename = $this->createTemporaryFile($html, 'html');
$result = $this->getOutput($filename, $options);
$this->unlink($filename);
return $result;
}
/**
* Defines the binary
*
* @param string $binary The path/name of the binary
*/
public function setBinary($binary)
{
$this->binary = $binary;
}
/**
* Returns the binary
*
* @return string
*/
public function getBinary()
{
return $this->binary;
}
/**
* Returns the command for the given input and output files
*
* @param string $input The input file
* @param string $output The ouput file
* @param array $options An optional array of options that will be used
* only for this command
*
* @return string
*/
public function getCommand($input, $output, array $options = array())
{
$options = $this->mergeOptions($options);
return $this->buildCommand($this->binary, $input, $output, $options);
}
/**
* Adds an option
*
* @param string $name The name
* @param mixed $default An optional default value
*/
protected function addOption($name, $default = null)
{
if (array_key_exists($name, $this->options)) {
throw new \InvalidArgumentException(sprintf('The option \'%s\' already exists.', $name));
}
$this->options[$name] = $default;
}
/**
* Adds an array of options
*
* @param array $options
*/
protected function addOptions(array $options)
{
foreach ($options as $name => $default) {
$this->addOption($name, $default);
}
}
/**
* Merges the given array of options to the instance options and returns
* the result options array. It does NOT change the instance options.
*
* @param array $options
*
* @return array
*/
protected function mergeOptions(array $options)
{
$mergedOptions = $this->options;
foreach ($options as $name => $value) {
if (!array_key_exists($name, $mergedOptions)) {
throw new \InvalidArgumentException(sprintf('The option \'%s\' does not exist.', $name));
}
$mergedOptions[$name] = $value;
}
return $mergedOptions;
}
/**
* Checks the specified output
*
* @param string $output The output filename
* @param string $command The generation command
*
* @throws RuntimeException if the output file generation failed
*/
protected function checkOutput($output, $command)
{
// the output file must exist
if (!$this->fileExists($output)) {
throw new \RuntimeException(sprintf(
'The file \'%s\' was not created (command: %s).',
$output, $command
));
}
// the output file must not be empty
if (0 === $this->filesize($output)) {
throw new \RuntimeException(sprintf(
'The file \'%s\' was created but is empty (command: %s).',
$output, $command
));
}
}
/**
* Checks the process return status
*
* @param int $status The exit status code
* @param string $stdout The stdout content
* @param string $stderr The stderr content
* @param string $command The run command
*
* @throws RuntimeException if the output file generation failed
*/
protected function checkProcessStatus($status, $stdout, $stderr, $command)
{
if (0 !== $status and '' !== $stderr) {
throw new \RuntimeException(sprintf(
'The exit status code \'%s\' says something went wrong:'."\n"
.'stderr: "%s"'."\n"
.'stdout: "%s"'."\n"
.'command: %s.',
$status, $stderr, $stdout, $command
));
}
}
/**
* Creates a temporary file.
* The file is not created if the $content argument is null
*
* @param string $content Optional content for the temporary file
* @param string $extension An optional extension for the filename
*
* @return string The filename
*/
protected function createTemporaryFile($content = null, $extension = null)
{
$filename = rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . uniqid('knp_snappy', true);
if (null !== $extension) {
$filename .= '.'.$extension;
}
if (null !== $content) {
file_put_contents($filename, $content);
}
return $filename;
}
/**
* Builds the command string
*
* @param string $binary The binary path/name
* @param string/array $input Url(s) or file location(s) of the page(s) to process
* @param string $output File location to the image-to-be
* @param array $options An array of options
*
* @return string
*/
protected function buildCommand($binary, $input, $output, array $options = array())
{
$command = $binary;
$escapedBinary = escapeshellarg($binary);
if (is_executable($escapedBinary)) {
$command = $escapedBinary;
}
foreach ($options as $key => $option) {
if (null !== $option && false !== $option) {
if (true === $option) {
$command .= ' --'.$key;
} elseif (is_array($option)) {
if ($this->isAssociativeArray($option)) {
foreach ($option as $k => $v) {
$command .= ' --'.$key.' '.escapeshellarg($k).' '.escapeshellarg($v);
}
} else {
foreach ($option as $v) {
$command .= " --".$key." ".escapeshellarg($v);
}
}
} else {
$command .= ' --'.$key." ".escapeshellarg($option);
}
}
}
if (is_array($input)) {
foreach ($input as $i) {
$command .= ' '.escapeshellarg($i).' ';
}
$command .= escapeshellarg($output);
} else {
$command .= ' '.escapeshellarg($input).' '.escapeshellarg($output);
}
return $command;
}
/**
* Return true if the array is an associative array
* and not an indexed array
*
* @param array $array
*
* @return boolean
*/
protected function isAssociativeArray(array $array)
{
return (bool) count(array_filter(array_keys($array), 'is_string'));
}
/**
* Executes the given command via shell and returns the complete output as
* a string
*
* @param string $command
*
* @return array(status, stdout, stderr)
*/
protected function executeCommand($command)
{
if (class_exists('Symfony\Component\Process\Process')) {
$process = new \Symfony\Component\Process\Process($command, NULL, $this->env);
if ($this->timeout !== false) {
$process->setTimeout($this->timeout);
}
} else {
$process = new Process($command, $this->env);
}
$process->run();
return array(
$process->getExitCode(),
$process->getOutput(),
$process->getErrorOutput(),
);
}
/**
* Prepares the specified output
*
* @param string $filename The output filename
* @param boolean $overwrite Whether to overwrite the file if it already
* exist
*/
protected function prepareOutput($filename, $overwrite)
{
$directory = dirname($filename);
if ($this->fileExists($filename)) {
if (!$this->isFile($filename)) {
throw new \InvalidArgumentException(sprintf(
'The output file \'%s\' already exists and it is a %s.',
$filename, $this->isDir($filename) ? 'directory' : 'link'
));
} elseif (false === $overwrite) {
throw new Exceptions\FileAlreadyExistsException(sprintf(
'The output file \'%s\' already exists.',
$filename
));
} elseif (!$this->unlink($filename)) {
throw new \RuntimeException(sprintf(
'Could not delete already existing output file \'%s\'.',
$filename
));
}
} elseif (!$this->isDir($directory) && !$this->mkdir($directory)) {
throw new \RuntimeException(sprintf(
'The output file\'s directory \'%s\' could not be created.',
$directory
));
}
}
/**
* Wrapper for the "file_get_contents" function
*
* @param string $filename
*
* @return string
*/
protected function getFileContents($filename)
{
return file_get_contents($filename);
}
/**
* Wrapper for the "file_exists" function
*
* @param string $filename
*
* @return boolean
*/
protected function fileExists($filename)
{
return file_exists($filename);
}
/**
* Wrapper for the "is_file" method
*
* @param string $filename
*
* @return boolean
*/
protected function isFile($filename)
{
return is_file($filename);
}
/**
* Wrapper for the "filesize" function
*
* @param string $filename
*
* @return integer or FALSE on failure
*/
protected function filesize($filename)
{
return filesize($filename);
}
/**
* Wrapper for the "unlink" function
*
* @param string $filename
*
* @return boolean
*/
protected function unlink($filename)
{
return unlink($filename);
}
/**
* Wrapper for the "is_dir" function
*
* @param string $filename
*
* @return boolean
*/
protected function isDir($filename)
{
return is_dir($filename);
}
/**
* Wrapper for the mkdir function
*
* @param string $pathname
*
* @return boolean
*/
protected function mkdir($pathname)
{
return mkdir($pathname, 0777, true);
}
}