From 2e5ce49625c437ce2dc155802189cc992d1f72c6 Mon Sep 17 00:00:00 2001 From: Vincent Vanwaelscappel Date: Wed, 22 Sep 2021 10:26:26 +0200 Subject: [PATCH] wip #4697 @0.25 --- src/CommandLine/Git.php | 20 +++ src/CommandLine/Imagemagick.php | 94 +++++++++++++ src/CommandLine/Imagemagick/Round.php | 62 +++++++++ src/CommandLine/Phantomjs.php | 57 ++++++++ src/CommandLine/Poppler.php | 182 ++++++++++++++++++++++++++ src/CommandLine/Rsync.php | 173 ++++++++++++++++++++++++ src/Graphics/PDF.php | 12 ++ 7 files changed, 600 insertions(+) create mode 100644 src/CommandLine/Git.php create mode 100644 src/CommandLine/Imagemagick.php create mode 100644 src/CommandLine/Imagemagick/Round.php create mode 100644 src/CommandLine/Phantomjs.php create mode 100644 src/CommandLine/Poppler.php create mode 100644 src/CommandLine/Rsync.php create mode 100644 src/Graphics/PDF.php diff --git a/src/CommandLine/Git.php b/src/CommandLine/Git.php new file mode 100644 index 0000000..cbf2b49 --- /dev/null +++ b/src/CommandLine/Git.php @@ -0,0 +1,20 @@ +_repos = $repos; + $this->cd($repos); + } + + public function executeCmd($cmd) { + $this->setManualArg($cmd); + $this->execute(); + return $cmd . ' :: ' . file_get_contents($this->output); + } +} \ No newline at end of file diff --git a/src/CommandLine/Imagemagick.php b/src/CommandLine/Imagemagick.php new file mode 100644 index 0000000..90eaf03 --- /dev/null +++ b/src/CommandLine/Imagemagick.php @@ -0,0 +1,94 @@ +_src; + } + + public function getDest() + { + return $this->_dest; + } + + public function setSrc($src) + { + $this->_src = $src; + return $this; + } + + public function setDest($dest) + { + $this->_dest = $dest; + return $this; + } + + public function execute($fonction = 'shell_exec') + { + + $this->_setConversionArgs(); + if ($this->getSrc()) { + $this->setArg(null, $this->getSrc()); + } + if ($this->getDest()) { + $this->setArg(null, $this->getDest()); + } + parent::execute($fonction); + } + + protected function _setConversionArgs() + { + + } + + public static function append($images, $dest, $way = 'horizontal') + { + $cl = new self(); + if (!is_array($images)) { + $images = array($images); + } + foreach ($images as $image) { + $cl->setArg(null, $image); + } + if ($way == 'horizontal') { + $sign = '+'; + } else { + $sign = '-'; + } + $cl->setArg(null, $sign . 'append'); + $cl->setArg(null, $dest); + $cl->execute(); + $cl->debug(); + } + + public static function addBorder($image, $dest, $size = 0, $color = '#ffffff') + { + if ($size <= 0) { + copy($image, $dest); + return; + } + + $cl = new self(); + $cl->setArg(null, $image); + $cl->setManualArg('-bordercolor "' . $color . '"'); + $cl->setManualArg('-border ' . $size); + $cl->setArg(null, $dest); + $cl->execute(); + $cl->debug(); + } + +} diff --git a/src/CommandLine/Imagemagick/Round.php b/src/CommandLine/Imagemagick/Round.php new file mode 100644 index 0000000..b5b9a36 --- /dev/null +++ b/src/CommandLine/Imagemagick/Round.php @@ -0,0 +1,62 @@ +_radius; + } + + public function setRadius($radius) + { + $this->_radius = $radius; + return $this; + } + + protected function _setConversionArgs() + { + $dim = getimagesize($this->getSrc()); + $ra = round($dim[0] * ($this->getRadius() / 100)); + $this->setArg(null, $this->getSrc()); + $c = '\( +clone -alpha extract '; + $c .= '-draw \'fill black polygon 0,0 0,' . $ra . ' ' . $ra . ',0 fill white circle ' . $ra . ',' . $ra . ' ' . $ra . ',0\' '; + $c .= '\( +clone -flip \) -compose Multiply -composite '; + $c .= '\( +clone -flop \) -compose Multiply -composite '; + $c .= '\) -alpha off -compose CopyOpacity -composite '; + $this->setManualArg($c); + } + + public function execute($fonction = 'shell_exec') + { + $res = parent::execute($fonction); + + $d = $this->getDest(); + + if (file_exists($d) && !filesize($d)) { + unlink($d); + } + + if (!file_exists($d) || !filesize($d)) { + if (file_exists($d . '-0')) { + rename($d . '-0', $d); + } + } + if (!file_exists($d) || !filesize($d)) { + $e = explode('.', $d); + $ext = array_pop($e); + $zero = implode('.', $e) . '-0' . '.' . $ext; + + if (file_exists($zero)) { + rename($zero, $d); + } + } + return $res; + } + +} diff --git a/src/CommandLine/Phantomjs.php b/src/CommandLine/Phantomjs.php new file mode 100644 index 0000000..603e4d4 --- /dev/null +++ b/src/CommandLine/Phantomjs.php @@ -0,0 +1,57 @@ +getOption('bin'); + + if (isset($bin['phantomjs'])) { + $exe = $bin['phantomjs']; + } + } + + $cache = CACHE_PATH . '/phantomjs/'; + + if (!file_exists($cache . 'cache')) { + mkdir($cache . 'cache', 0777, true); + } + + parent::__construct($exe, $output, $error); + $this->setArg('disk-cache', 'false'); + $this->setArg('ssl-protocol', 'any'); + $this->setArg('ignore-ssl-errors', 'true'); + $this->setArg('local-storage-path', $cache . 'cache'); + $this->setArg('cookies-file', $cache . 'cookies.txt'); + $this->setArg('output-encoding', 'utf8'); + $this->setArg(null, $script); + } + + public static function html2pdf($url, $dest, $format = '210mm*297mm', $script = null, $exe = '/usr/local/bin/phantomjs') + { + $dir = dirname($dest); + if (!file_exists($dir)) { + mkdir($dir, 0777, true); + } + + if (null === $script) { + $script = PUBLIC_PATH . '/CubeIT/js/phantomjs/rasterize.js'; + } + + $cl = new CubeIT_CommandLine_Phantomjs($script, null, true, $exe); + $cl->setArg(null, '"' . $url . '"'); + $cl->setArg(null, '"' . $dest . '"'); + $cl->setArg(null, '"' . $format . '"'); + $cl->execute(); + $cl->debug(); + + return $cl; + } + +} diff --git a/src/CommandLine/Poppler.php b/src/CommandLine/Poppler.php new file mode 100644 index 0000000..20e30a9 --- /dev/null +++ b/src/CommandLine/Poppler.php @@ -0,0 +1,182 @@ + 300, + 'quality' => '95', + 'antialias' => true, + 'format' => 'jpeg', + 'internalformat' => 'png'); + + $options = array_merge($defaultOptions, $options); + $options['factor'] = $options['resolution'] / 72; + + if ($options['format'] === 'jpeg') { + $extension = 'jpg'; + } else { + $extension = $options['format']; + } + + $res = $to . '.' . $extension; + + $cacheFile = null; + + Files::mkdir($cache); + + if (null !== $cache) { + $f = $file . '/' . filemtime($file) . '++' . json_encode($rect) . '**' . json_encode($options) . '||' . $page . '!!'; + $hash = hash('sha256', $f); + $cacheFile = $cache . '/' . $hash . '.' . $extension; + if (file_exists($cacheFile)) { + copy($cacheFile, $res); + return $res; + } + } + +// error_log('####--------------####'); +// error_log('___ Resolution: ' . $options['resolution']); +// error_log('___ Factor: ' . $factor); +// error_log('extractArea: '. $f); +// error_log("CACHE MISS: $cacheFile"); + + + $pdftoppm = new CommandLine('pdftoppm'); + $pdftoppm->setArg('r', $options['resolution']); + if ($options['format'] === 'png') { + $pdftoppm->setArg('-' . $options['format']); + } + $aa = $options['antialias'] ? 'yes' : 'no'; + $pdftoppm->setArg('-aa', $aa); + $pdftoppm->setArg('-aaVector', $aa); + $pdftoppm->setArg('-cropbox'); + $pdftoppm->setArg('-freetype', 'yes'); + $pdftoppm->setArg('-singlefile'); + $pdftoppm->setArg('-f', $page); + $pdftoppm->setArg('-l', $page); + $pdftoppm->setArg('-x', round($rect['x'] * $options['factor'])); + $pdftoppm->setArg('-y', round($rect['y'] * $options['factor'])); + $pdftoppm->setArg('-W', round($rect['width'] * $options['factor'])); + $pdftoppm->setArg('-H', round($rect['height'] * $options['factor'])); + $pdftoppm->setArg(null, $file); + $pdftoppm->setArg(null, $to); + $pdftoppm->execute(); + $pdftoppm->debug(); + + if ($options['format'] === 'jpeg') { + $cjpeg = new CommandLine('cjpeg', $res); + $cjpeg->setArg('-quality', $options['quality']); + $cjpeg->setArg(null, $to . '.ppm'); + $cjpeg->execute(); + } + + if (null !== $cacheFile) { + copy($res, $cacheFile); + } + + return $res; + + } + + protected static function _pdftojpeg($file, $to, $nbpages, $options = array()) + { + /* + * pdftoppm version 0.48.0 +Copyright 2005-2016 The Poppler Developers - http://poppler.freedesktop.org +Copyright 1996-2011 Glyph & Cog, LLC +Usage: pdftoppm [options] [PDF-file [PPM-file-prefix]] + -f : first page to print + -l : last page to print + -o : print only odd pages + -e : print only even pages + -singlefile : write only the first page and do not add digits + -r : resolution, in DPI (default is 150) + -rx : X resolution, in DPI (default is 150) + -ry : Y resolution, in DPI (default is 150) + -scale-to : scales each page to fit within scale-to*scale-to pixel box + -scale-to-x : scales each page horizontally to fit in scale-to-x pixels + -scale-to-y : scales each page vertically to fit in scale-to-y pixels + -x : x-coordinate of the crop area top left corner + -y : y-coordinate of the crop area top left corner + -W : width of crop area in pixels (default is 0) + -H : height of crop area in pixels (default is 0) + -sz : size of crop square in pixels (sets W and H) + -cropbox : use the crop box rather than media box + -mono : generate a monochrome PBM file + -gray : generate a grayscale PGM file + -png : generate a PNG file + -jpeg : generate a JPEG file + -tiff : generate a TIFF file + -tiffcompression : set TIFF compression: none, packbits, jpeg, lzw, deflate + -freetype : enable FreeType font rasterizer: yes, no + -thinlinemode : set thin line mode: none, solid, shape. Default: none + -aa : enable font anti-aliasing: yes, no + -aaVector : enable vector anti-aliasing: yes, no + -opw : owner password (for encrypted files) + -upw : user password (for encrypted files) + -q : don't print any messages or errors + -v : print copyright and version info + -h : print usage information + -help : print usage information + --help : print usage information + -? : print usage information + + */ + + $defaultOptions = array('resolution' => 150, + 'quality' => '80', + 'antialias' => true, + 'format' => 'jpeg', + 'internalformat' => 'png'); + + $options = array_merge($defaultOptions, $options); + + $pdftoppm = new CommandLine('pdftoppm'); + $pdftoppm->setArg('r', $options['resolution']); + $pdftoppm->setArg('-' . $options['internalformat']); + $aa = $options['antialias'] ? 'yes' : 'no'; + $pdftoppm->setArg('-aa', $aa); + $pdftoppm->setArg('-aaVector', $aa); + $pdftoppm->setArg('-cropbox'); + $pdftoppm->setArg('-freetype', 'yes'); + $pdftoppm->setArg(null, $file); + $pdftoppm->setArg(null, $to . '/p'); + $pdftoppm->execute(); + //$pdftoppm->debug(); + + + $chars = strlen($nbpages); + for ($i = 1; $i <= $nbpages; $i++) { + $f = $to . '/p-' . Math::fill($i, $chars, '0') . '.' . self::_format2ext($options['internalformat']); + $d = $to . '/p' . $i . '.' . self::_format2ext($options['format']); + + if ($options['internalformat'] != $options['format']) { + $convert = new Imagemagick(); + $convert->setSrc($f); + $convert->setDest($d); + $convert->execute(); + //$convert->debug(); + } else { + rename($f, $d); + } + chmod($d, 0777); + } + } + + protected static function _format2ext($format) + { + if ($format === 'jpeg') { + return 'jpg'; + } + return $format; + } + +} diff --git a/src/CommandLine/Rsync.php b/src/CommandLine/Rsync.php new file mode 100644 index 0000000..df4caef --- /dev/null +++ b/src/CommandLine/Rsync.php @@ -0,0 +1,173 @@ +_sshKey; + } + + public function setSshKey($sshKey) + { + $this->_sshKey = $sshKey; + return $this; + } + + public function getDeleteExcluded() + { + return $this->_deleteExcluded; + } + + public function setDeleteExcluded($deleteExcluded = true) + { + $this->_deleteExcluded = $deleteExcluded; + return $this; + } + + public function getPort() + { + return $this->_port; + } + + public function setPort($port) + { + $this->_port = $port; + return $this; + } + + public function getSrc() + { + return $this->_src; + } + + public function getDest() + { + return $this->_dest; + } + + public function getMirror() + { + return $this->_mirror; + } + + public function setSrc($src) + { + $this->_src = $src; + return $this; + } + + public function setDest($dest) + { + $this->_dest = $dest; + return $this; + } + + public function setMirror($mirror) + { + $this->_mirror = $mirror; + return $this; + } + + public function addExclude($exclude) + { + $this->_excludes[] = $exclude; + } + + /** + * @return string + */ + public function getProg() + { + return $this->_prog; + } + + /** + * @param string $prog + */ + public function setProg($prog) + { + $this->_prog = $prog; + } + + public function _fixPath($path) + { + $path = preg_replace("|\\+|", '/', $path); + if (preg_match('|^([a-z]):(.*)$|i', $path, $matches)) { + $path = '/cygdrive/' . $matches[1] . '/' . ltrim($matches[2], '/'); + } + return $path; + } + + protected function _preExecute() + { + $dest = $this->getDest(); + $port = $this->getPort(); + $src = $this->getSrc(); + $mirror = $this->getMirror(); + + + $destDistant = stristr($dest, '@'); + if ($destDistant) { + list($distServer, $distDir) = explode(':', $dest, 2); + $distDir = $this->_fixPath($distDir); + $dest = $distServer . ':\'' . $distDir . '\''; + } + + + if (!file_exists($dest)) { + if (!$destDistant) { + Files::mkdir($dest); + } else { + `ssh -p $port $distServer "mkdir -p $distDir"`; + } + } + + if ($this->getDeleteExcluded()) { + $this->setArg('delete-excluded'); + } + $this->setArg('t'); + $this->setArg('r'); + $this->setArg('v'); + foreach ($this->_excludes as $e) { + $this->setArg('exclude', $e); + } + if ($mirror) { + $this->setArg('force'); + $this->setArg('delete-after'); + } + if ($destDistant) { + $ssh = 'ssh -p ' . $port; + if (null !== $this->getSshKey()) { + $ssh .= ' -i ' . $this->getSshKey(); + } + $this->setArg('e', $ssh); + } + $this->setArg(null, rtrim($src, '/') . '/'); + $this->setArg(null, rtrim($dest, '/') . '/'); + } + + public function __construct($src, $dest, $mirror = false, $output = null, $error = true) + { + parent::__construct($this->_prog, $output, $error); + + $this->setSrc($src); + $this->setDest($dest); + $this->setMirror($mirror); + } + +} diff --git a/src/Graphics/PDF.php b/src/Graphics/PDF.php new file mode 100644 index 0000000..fe51490 --- /dev/null +++ b/src/Graphics/PDF.php @@ -0,0 +1,12 @@ +