Skip to content

Commit ad9c03c

Browse files
author
Marvin Kuhn
committed
initial commit 👋
1 parent da0bcbd commit ad9c03c

20 files changed

+544
-0
lines changed

.editorconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
; This file is for unifying the coding style for different editors and IDEs.
2+
; More information at http://editorconfig.org
3+
4+
root = true
5+
6+
[*]
7+
charset = utf-8
8+
indent_size = 4
9+
indent_style = space
10+
end_of_line = lf
11+
insert_final_newline = true
12+
trim_trailing_whitespace = true
13+
14+
[*.md]
15+
trim_trailing_whitespace = false

.gitatributes

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Path-based git attributes
2+
# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
3+
4+
# Ignore all test and documentation with "export-ignore".
5+
/.gitattributes export-ignore
6+
/.gitignore export-ignore
7+
/phpunit.xml.dist export-ignore
8+
/tests export-ignore
9+
/.editorconfig export-ignore

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
build
2+
composer.lock
3+
docs
4+
vendor
5+
tests/temp
6+
.phpintel

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Changelog
2+
This is the chnagelog of the package `breadlesscode/office-converter`.

CONTRIBUTING.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Contributing
2+
3+
Contributions are **welcome** and will be fully **credited**.
4+
5+
We accept contributions via Pull Requests on [Github](https://github.com/spatie/menu).
6+
7+
8+
## Pull Requests
9+
10+
- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer).
11+
- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date.
12+
- **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option.
13+
- **Create feature branches** - Don't ask us to pull from your master branch.
14+
- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
15+
- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting.

README.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Office converter (with LibreOffice)
2+
This package is for converting office formats to something else. You can generate Thumbnails, PDFs etc..
3+
4+
## Requirements
5+
This package needs [LibreOffice](https://libreoffice.org/) for the convertion.
6+
7+
## Which extension can be converted to what?
8+
You can check the following files:
9+
- [WriterProgramm.php](./src/Programms/WriterProgramm.php)
10+
- [CalcProgramm.php](./src/Programms/CalcProgramm.php)
11+
- [DrawProgramm.php](./src/Programms/DrawProgramm.php)
12+
- [ImpressProgramm.php](./src/Programms/ImpressProgramm.php)
13+
14+
## Installation
15+
16+
This package can be installed through Composer.
17+
```bash
18+
composer require breadlesscode/office-conveter
19+
```
20+
## How to use
21+
22+
```php
23+
use \Breadlesscode\Office\Converter;
24+
25+
Converter::file('Test.odt') // select a file for convertion
26+
->setLibreofficeBinaryPath('/usr/bin/libreoffice') // binary to the libreoffice binary
27+
->setTemporaryPath('./temp') // temporary directory for convertion
28+
->setTimeout(100) // libreoffice process timeout
29+
->save(__DIR__.'/lorem.pdf'); // save as pdf
30+
```
31+
32+
## Examples
33+
34+
### Save with original name in folder
35+
```php
36+
use Breadlesscode\Office\Converter;
37+
38+
Converter::file('./Test.odt')
39+
->save('./lorem', 'jpg');
40+
```
41+
### Save with custom name
42+
```php
43+
use Breadlesscode\Office\Converter;
44+
45+
Converter::file('./Test.odt')
46+
->save('./lorem.jpg');
47+
```
48+
## ToDo
49+
[ ] Rethinking parameter building process
50+
[ ] Add some more Tests
51+
52+
Ideas and PRs are welcome :)
53+
## Testing
54+
55+
``` bash
56+
$ composer test
57+
```
58+
## License
59+
60+
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

composer.json

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"name": "breadlesscode/office-converter",
3+
"description": "Convert office documents to something else",
4+
"keywords": [
5+
"office",
6+
"libre",
7+
"convert",
8+
"thumbnail",
9+
"pdf",
10+
"text",
11+
"export"
12+
],
13+
"license": "MIT",
14+
"authors": [
15+
{
16+
"name": "Marvin Kuhn",
17+
"email": "[email protected]",
18+
"homepage": "https://kuhnweblab.com/",
19+
"role": "Developer"
20+
}
21+
],
22+
"require": {
23+
"php": "^7.0",
24+
"symfony/process": "^3.3",
25+
"spatie/temporary-directory": "^1.0.0"
26+
},
27+
"require-dev": {
28+
"phpunit/phpunit": "^6.0"
29+
},
30+
"autoload": {
31+
"psr-4": {
32+
"Breadlesscode\\Office\\": "src"
33+
}
34+
},
35+
"autoload-dev": {
36+
"psr-4": {
37+
"Breadlesscode\\Office\\Test\\": "tests"
38+
}
39+
},
40+
"scripts": {
41+
"test": "vendor/bin/phpunit"
42+
},
43+
"config": {
44+
"sort-packages": true
45+
}
46+
}

phpunit.xml.dist

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit bootstrap="vendor/autoload.php"
3+
backupGlobals="false"
4+
backupStaticAttributes="false"
5+
colors="true"
6+
verbose="true"
7+
convertErrorsToExceptions="true"
8+
convertNoticesToExceptions="true"
9+
convertWarningsToExceptions="true"
10+
processIsolation="false"
11+
stopOnFailure="false">
12+
<testsuites>
13+
<testsuite name="Test Suite">
14+
<directory>tests</directory>
15+
</testsuite>
16+
</testsuites>
17+
<filter>
18+
<whitelist>
19+
<directory suffix=".php">src/</directory>
20+
</whitelist>
21+
</filter>
22+
</phpunit>

src/Converter.php

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
<?php
2+
3+
namespace Breadlesscode\Office;
4+
5+
use Spatie\TemporaryDirectory\TemporaryDirectory;
6+
use Symfony\Component\Process\Exception\ProcessFailedException;
7+
use Symfony\Component\Process\Process;
8+
use Breadlesscode\Office\Exception\ConverterException;
9+
10+
class Converter
11+
{
12+
public static $converters = [
13+
\Breadlesscode\Office\Programs\WriterProgram::class,
14+
\Breadlesscode\Office\Programs\CalcProgram::class,
15+
\Breadlesscode\Office\Programs\ImpressProgram::class,
16+
\Breadlesscode\Office\Programs\DrawProgram::class
17+
];
18+
19+
protected $paramters = ['--headless'];
20+
protected $fileInfo = null;
21+
protected $file = null;
22+
protected $converter = null;
23+
protected $binaryPath = 'libreoffice';
24+
protected $temporaryPath = 'temp';
25+
protected $timeout = 2000;
26+
27+
public function __construct(string $file, string $fileType = null)
28+
{
29+
if (!file_exists($file)) {
30+
throw new ConverterException("File ".$file." not found!", 1);
31+
}
32+
33+
$fileExtension = $fileType ?: pathinfo(realpath($file), PATHINFO_EXTENSION);
34+
35+
foreach (self::$converters as $converter) {
36+
if (!$converter::canHandleExtension($fileExtension)) {
37+
continue;
38+
}
39+
40+
$this->fileInfo = pathinfo($file);
41+
$this->file = $file;
42+
$this->converter = $converter;
43+
break;
44+
}
45+
46+
if ($this->file === null) {
47+
throw new ConverterException('Can not handle file type '.$fileExtension);
48+
}
49+
}
50+
51+
public static function canHandleExtension(string $fileExtension): bool
52+
{
53+
foreach (self::$converters as $converter) {
54+
if ($converter::canHandleExtension($fileExtension)) {
55+
return true;
56+
}
57+
}
58+
59+
return false;
60+
}
61+
public static function file(string $file, string $fileType = null)
62+
{
63+
return new static($file, $fileType);
64+
}
65+
66+
public function setLibreofficeBinaryPath(string $path)
67+
{
68+
$this->binaryPath = $path;
69+
70+
return $this;
71+
}
72+
73+
public function setTemporaryPath(string $path)
74+
{
75+
$this->temporaryPath = $path;
76+
77+
return $this;
78+
}
79+
80+
public function setTimeout(int $timeout)
81+
{
82+
$this->timeout = $timeout;
83+
84+
return $this;
85+
}
86+
87+
public function thumbnail(string $extension = 'jpg')
88+
{
89+
$this->save($this->fileInfo['dirname'].DIRECTORY_SEPARATOR.$this->getNewFilename($extension));
90+
}
91+
92+
public function text()
93+
{
94+
return trim($this->content('txt'));
95+
}
96+
97+
public function save(string $path, string $extension = null): bool
98+
{
99+
$pathInfo = pathinfo($path);
100+
$rename = is_null($extension);
101+
102+
if (is_null($extension)) {
103+
$extension = $pathInfo['extension'] ? $pathInfo['extension'] : $extension;
104+
}
105+
106+
if (!$this->isConvertable($extension)) {
107+
throw new ConverterException("Invalid conversion. Can not convert ".$this->fileInfo['extension']." to ".$extension, 1);
108+
}
109+
110+
111+
$this->setFilter($extension);
112+
$this->setOutputDir($rename ? $pathInfo['dirname'] : $path);
113+
$this->callLibreofficeBinary();
114+
115+
if ($rename) {
116+
// rename to new name
117+
$oldName = $pathInfo['dirname'].DIRECTORY_SEPARATOR.$this->getNewFilename($extension);
118+
$newName = $pathInfo['dirname'].DIRECTORY_SEPARATOR.$pathInfo['basename'];
119+
rename($oldName, $newName);
120+
}
121+
122+
return true;
123+
}
124+
125+
public function content(string $extension = null): string
126+
{
127+
if (!$this->isConvertable($extension)) {
128+
throw new ConverterException("Invalid conversion. Can not convert ".$this->fileInfo['extension']." to ".$extension, 1);
129+
}
130+
131+
$tempDir = (new TemporaryDirectory(__DIR__))
132+
->name('temp')
133+
->force()
134+
->create()
135+
->empty();
136+
137+
$this->setFilter($extension);
138+
$this->setOutputDir($tempDir->path());
139+
$this->callLibreofficeBinary();
140+
141+
$content = file_get_contents($tempDir->path($this->getNewFilename($extension)));
142+
$tempDir->delete();
143+
144+
return $content;
145+
}
146+
147+
protected function getNewFilename(string $extension)
148+
{
149+
$path = $this->file;
150+
151+
return str_replace($this->fileInfo['extension'], $extension, $this->fileInfo['basename']);
152+
}
153+
154+
protected function setOutputDir(string $dir)
155+
{
156+
$this->paramters[] = '--outdir '.$this->escapeArgument($dir);
157+
}
158+
159+
protected function setFilter(string $extension, string $filter = '')
160+
{
161+
$arg = empty($filter) ? $extension : $extension.':'.$filter;
162+
163+
$this->paramters[] = '--convert-to '.$this->escapeArgument($arg);
164+
}
165+
166+
protected function escapeArgument(string $arg): string
167+
{
168+
return $arg;
169+
}
170+
171+
protected function callLibreofficeBinary(): string
172+
{
173+
// add file to convert
174+
$filePath = $this->file;
175+
$this->paramters[] = $filePath;
176+
// glue parameters
177+
$cliStr = $this->binaryPath;
178+
$cliStr.= ' '.implode(' ', $this->paramters);
179+
// start convert process
180+
$process = (new Process($cliStr))->setTimeout($this->timeout);
181+
$process->run();
182+
183+
if (! $process->isSuccessful()) {
184+
throw new ProcessFailedException($process);
185+
}
186+
187+
return $process->getOutput();
188+
}
189+
190+
protected function isConvertable(string $extension): bool
191+
{
192+
if (is_null($extension)) {
193+
throw new ConverterException('No extension is set.');
194+
}
195+
196+
return $this->converter::canConvertTo($extension);
197+
}
198+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
namespace Breadlesscode\Office\Exception;
3+
4+
5+
class ConverterException extends \Exception
6+
{
7+
8+
}

0 commit comments

Comments
 (0)