Compare commits

...

8 Commits

12 changed files with 401 additions and 45 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/vendor

View File

@ -28,6 +28,10 @@
<bugs>https://github.com/e-alfred/nextcloud-printer/issues</bugs>
<screenshot>https://github.com/e-alfred/nextcloud-printer/raw/master/screenshots/printer.gif</screenshot>
<dependencies>
<nextcloud min-version="16" max-version="19" />
<nextcloud min-version="17" max-version="19" />
</dependencies>
<settings>
<admin>OCA\Printer\Settings\Admin\AllowedGroups</admin>
<admin-section>OCA\Printer\Settings\Admin\Section</admin-section>
</settings>
</info>

5
composer.json Normal file
View File

@ -0,0 +1,5 @@
{
"require": {
"symfony/process": "^4.4"
}
}

3
css/admin.css Normal file
View File

@ -0,0 +1,3 @@
#printer_admin input {
vertical-align: middle;
}

1
img/app-dark.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="77.670189mm" height="70.065002mm" viewBox="0 0 293.55662 264.81261"><g color="#000" transform="matrix(3.77953 0 0 3.77953 1021.4277 -374.84951)"><path d="M-270.25274222 121.24117818v48.00275296h77.67018542v-48.00275296h-16.81964696v23.43422756h-44.03090209v-23.43422756z" overflow="visible" paint-order="stroke fill markers" style="marker:none"/><rect width="29.289507" height="38.742561" x="-246.06248" y="99.178932" overflow="visible" paint-order="stroke fill markers" rx="0" ry="0" style="marker:none"/></g></svg>

After

Width:  |  Height:  |  Size: 563 B

65
js/admin.js Normal file
View File

@ -0,0 +1,65 @@
let elements = []
const selector = '#printer-message';
const appConfig = (name, value, callbacks) => {
OCP.AppConfig.setValue('printer', name, value, callbacks)
}
const saveSettings = (key) => {
const element = elements.get(key)
let value
let name
if (jQuery(element).is('[data-checkbox]')) {
name = jQuery(element).attr('data-name')
const inputs = jQuery('input[name="' + name + '[]"]:checked')
value = []
inputs.each((i, v) => {
value.push(v.value)
})
value = JSON.stringify(value)
} else {
name = jQuery(element).attr('name')
value = jQuery(element).val()
}
const size = elements.length
if (name === 'cache') {
++value
}
const callbacks = {
success: () => {
OC.msg.finishedSuccess(
selector,
t('printer', (key + 1) + '/' + size)
)
if (key < size - 1) {
saveSettings(++key)
} else {
OC.msg.finishedSuccess(selector, t('printer', 'Saved'))
}
},
error: () => {
OC.msg.finishedError(selector, t('printer', 'Error while saving "' + element + '"'))
}
}
appConfig(name, value, callbacks)
}
jQuery(document).ready(() => {
elements = jQuery('.printer-setting')
jQuery('#printer-save').on('click', (event) => {
event.preventDefault()
OC.msg.startSaving(selector)
saveSettings(0)
});
});

64
lib/Config.php Normal file
View File

@ -0,0 +1,64 @@
<?php
declare(strict_types=1);
namespace OCA\Printer;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IConfig;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\Security\ISecureRandom;
class Config
{
/**
* @var IConfig
*/
protected $config;
/**
* @var ITimeFactory
*/
protected $timeFactory;
/**
* @var IGroupManager
*/
private $groupManager;
/**
* @var ISecureRandom
*/
private $secureRandom;
public function __construct(IConfig $config, IGroupManager $groupManager)
{
$this->config = $config;
$this->groupManager = $groupManager;
}
/**
* @return string[]
*/
public function getAllowedGroupIds(): array
{
$groups = $this->config->getAppValue('printer', 'allowed_groups', '[]');
$groups = json_decode($groups, true);
return \is_array($groups) ? $groups : [];
}
public function isDisabledForUser(IUser $user): bool
{
$allowedGroups = $this->getAllowedGroupIds();
if (empty($allowedGroups)) {
return false;
}
$userGroups = $this->groupManager->getUserGroupIds($user);
return empty(array_intersect($allowedGroups, $userGroups));
}
}

View File

@ -1,59 +1,79 @@
<?php
namespace OCA\Printer\Controller;
use OCA\Printer\Config;
use OCA\Printer\Service\Printer;
use OCP\AppFramework\Controller;
use OCP\IRequest;
use OC\Files\Filesystem;
use OCP\AppFramework\Http\JSONResponse;
use OCP\IRequest;
use OCP\IUserSession;
use Symfony\Component\Process\Exception\ProcessFailedException;
class PrinterController extends Controller
{
/**
* @var OC\L10N\LazyL10N
*/
protected $language;
class PrinterController extends Controller {
/**
* @var Printer
*/
protected $printer;
protected $language;
/**
* @var Config
*/
protected $config;
public function __construct($appName, IRequest $request) {
public function __construct(string $appName, IRequest $request, Printer $printer, Config $config)
{
parent::__construct($appName, $request);
parent::__construct($appName, $request);
$this->language = \OC::$server->getL10N('printer');
$this->printer = $printer;
$this->config = $config;
}
// get i10n
$this->language = \OC::$server->getL10N('printer');
/**
* @NoAdminRequired
*/
public function printfile(string $sourcefile, string $orientation): JSONResponse
{
$file = \OC\Files\Filesystem::getLocalFile($sourcefile);
}
$success = [
'response' => 'success',
'msg' => $this->language->t('Print succeeded!'),
];
/**
* callback function to get md5 hash of a file
* @NoAdminRequired
* @param (string) $sourcefile - filename
* @param (string) $orientation - Orientation of printed file
*/
public function printfile($sourcefile, $orientation) {
if($orientation === "landscape") {
$filefullpath = \OC\Files\Filesystem::getLocalFile($sourcefile);
exec('lpr "' . $filefullpath . '"');
return new JSONResponse(
array(
'response' => 'success',
'msg' => $this->language->t('Print succeeded!')
)
);
}
$error = [
'response' => 'error',
'msg' => $this->language->t('Print failed'),
];
if($orientation === "portrait"){
$filefullpath = \OC\Files\Filesystem::getLocalFile($sourcefile);
exec('lpr -o orientation-requested=4 "' . $filefullpath . '"');
return new JSONResponse(
array(
'response' => 'success',
'msg' => $this->language->t('Print succeeded!')
)
);
} else {
return new JSONResponse(
array(
'response' => 'error',
'msg' => $this->language->t('Print failed')
)
);
};
}
$notAllowed = [
'response' => 'error',
'msg' => $this->language->t('User not allowed'),
];
$user = \OC::$server[IUserSession::class]->getUser();
if (!$user || $this->config->isDisabledForUser($user)) {
return new JSONResponse($notAllowed);
}
if (!$this->printer->isValidOrientation($orientation)) {
return new JSONResponse($error);
}
try {
$this->printer->print($file, $orientation);
return new JSONResponse($success);
} catch (ProcessFailedException $exception) {
return new JSONResponse($error);
}
}
}

44
lib/Service/Printer.php Normal file
View File

@ -0,0 +1,44 @@
<?php
namespace Service;
namespace OCA\Printer\Service;
use Symfony\Component\Process\Process;
/**
* class Printer.
*
* @author Simon Vieille <simon@deblan.fr>
*/
class Printer
{
public function print(string $file, string $orientation)
{
$options = [
'landscape' => [
'lpr',
$file,
],
'portrait' => [
'lpr',
'-o',
'orientation-requested=4',
$file,
],
];
$process = new Process($options[$orientation]);
$process->mustRun();
}
/**
* Validates an orientation.
*/
public function isValidOrientation(string $orientation): bool
{
return in_array($orientation, [
'landscape',
'portrait',
]);
}
}

View File

@ -0,0 +1,63 @@
<?php
declare(strict_types=1);
namespace OCA\Printer\Settings\Admin;
use OCA\Printer\Config;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IGroupManager;
use OCP\IInitialStateService;
use OCP\Settings\ISettings;
class AllowedGroups implements ISettings
{
/**
* @var Config
*/
private $config;
/**
* @var IInitialStateService
*/
private $initialStateService;
/**
* @var IGroupManager
*/
private $groupManager;
public function __construct(Config $config, IInitialStateService $initialStateService, IGroupManager $groupManager)
{
$this->config = $config;
$this->initialStateService = $initialStateService;
$this->groupManager = $groupManager;
}
public function getForm(): TemplateResponse
{
$this->initialStateService->provideInitialState(
'printer',
'allowed_groups',
$this->config->getAllowedGroupIds()
);
$groups = $this->groupManager->search('', 100);
$allowedGroups = $this->config->getAllowedGroupIds();
return new TemplateResponse('printer', 'settings/admin/allowed-groups', [
'groups' => $groups,
'allowedGroups' => $allowedGroups,
], '');
}
public function getSection(): string
{
return 'printer';
}
public function getPriority(): int
{
return 10;
}
}

View File

@ -0,0 +1,48 @@
<?php
declare(strict_types=1);
namespace OCA\Printer\Settings\Admin;
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\Settings\IIconSection;
class Section implements IIconSection
{
/**
* @var IL10N
*/
private $l;
/**
* @var IURLGenerator
*/
private $url;
public function __construct(IURLGenerator $url, IL10N $l)
{
$this->url = $url;
$this->l = $l;
}
public function getIcon(): string
{
return $this->url->imagePath('printer', 'app-dark.svg');
}
public function getID(): string
{
return 'printer';
}
public function getName(): string
{
return $this->l->t('Printer');
}
public function getPriority(): int
{
return 70;
}
}

View File

@ -0,0 +1,38 @@
<?php
style('printer', 'admin');
script('printer', 'admin');
?>
<div id="printer_admin">
<div class="section">
<h2><?php p($l->t('Limit to groups')) ?></h2>
<p class="settings-hint">
<?php p($l->t('When at least one group is selected, only people of the listed groups can print.')); ?>
</p>
<ul class="printer-setting" data-name="allowed_groups" data-checkbox>
<?php foreach ($_['groups'] as $group): ?>
<li>
<input
type="checkbox"
id="allowed_group_<?php echo $group->getGid() ?>"
name="allowed_groups[]"
value="<?php p($group->getGid()) ?>"
<?php if (in_array($group->getGid(), $_['allowedGroups'])): ?>
checked
<?php endif ?>
>
<label for="allowed_group_<?php echo $group->getGid() ?>">
<?php p($group->getDisplayName()) ?>
</label>
</li>
<?php endforeach ?>
</ul>
<button id="printer-save" class="btn btn-info">
<?php p($l->t('Save')); ?>
</button>
<span id="printer-message" class="msg"></span>
</div>
</div>