dolibarr 21.0.0-alpha
printgcp.modules.php
Go to the documentation of this file.
1<?php
2/*
3 * Copyright (C) 2014-2024 Frédéric France <frederic.france@free.fr>
4 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 * or see https://www.gnu.org/
19 */
20
27include_once DOL_DOCUMENT_ROOT.'/core/modules/printing/modules_printing.php';
28require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php';
29
30use OAuth\Common\Storage\DoliStorage;
31use OAuth\Common\Consumer\Credentials;
32
37{
41 public $name = 'printgcp';
42
46 public $desc = 'PrintGCPDesc';
47
51 public $picto = 'printer';
52
56 public $active = 'PRINTING_PRINTGCP';
57
61 public $conf = array();
62
66 public $google_id = '';
67
71 public $google_secret = '';
72
76 public $db;
77
78 private $OAUTH_SERVICENAME_GOOGLE = 'Google';
79
80 const LOGIN_URL = 'https://accounts.google.com/o/oauth2/token';
81 const PRINTERS_SEARCH_URL = 'https://www.google.com/cloudprint/search';
82 const PRINTERS_GET_JOBS = 'https://www.google.com/cloudprint/jobs';
83 const PRINT_URL = 'https://www.google.com/cloudprint/submit';
84
85
91 public function __construct($db)
92 {
93 global $conf, $langs, $dolibarr_main_url_root;
94
95 // Define $urlwithroot
96 $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
97 $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
98 //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
99
100 $this->db = $db;
101
102 if (!$conf->oauth->enabled) {
103 $this->conf[] = array(
104 'varname' => 'PRINTGCP_INFO',
105 'info' => $langs->transnoentitiesnoconv("WarningModuleNotActive", "OAuth"),
106 'type' => 'info',
107 );
108 } else {
109 $keyforprovider = ''; // @FIXME
110
111 $this->google_id = getDolGlobalString('OAUTH_GOOGLE_ID');
112 $this->google_secret = getDolGlobalString('OAUTH_GOOGLE_SECRET');
113 // Token storage
114 $storage = new DoliStorage($this->db, $conf, $keyforprovider);
115 //$storage->clearToken($this->OAUTH_SERVICENAME_GOOGLE);
116 // Setup the credentials for the requests
117 $credentials = new Credentials(
118 $this->google_id,
119 $this->google_secret,
120 $urlwithroot.'/core/modules/oauth/google_oauthcallback.php'
121 );
122 $access = ($storage->hasAccessToken($this->OAUTH_SERVICENAME_GOOGLE) ? 'HasAccessToken' : 'NoAccessToken');
123 $serviceFactory = new \OAuth\ServiceFactory();
124 $apiService = $serviceFactory->createService($this->OAUTH_SERVICENAME_GOOGLE, $credentials, $storage, array());
125 '@phan-var-force OAuth\OAuth2\Service\Google $apiService'; // createService is only ServiceInterface
126 $token_ok = true;
127 try {
128 $token = $storage->retrieveAccessToken($this->OAUTH_SERVICENAME_GOOGLE);
129 } catch (Exception $e) {
130 $this->errors[] = $e->getMessage();
131 $token_ok = false;
132 }
133
134 $expire = false;
135 // Is token expired or will token expire in the next 30 seconds
136 if ($token_ok) {
137 $expire = ($token->getEndOfLife() !== -9002 && $token->getEndOfLife() !== -9001 && time() > ($token->getEndOfLife() - 30));
138 }
139
140 // Token expired so we refresh it
141 if ($token_ok && $expire) {
142 try {
143 // il faut sauvegarder le refresh token car google ne le donne qu'une seule fois
144 $refreshtoken = $token->getRefreshToken();
145 $token = $apiService->refreshAccessToken($token);
146 $token->setRefreshToken($refreshtoken);
147 $storage->storeAccessToken($this->OAUTH_SERVICENAME_GOOGLE, $token);
148 } catch (Exception $e) {
149 $this->errors[] = $e->getMessage();
150 }
151 }
152 if ($this->google_id != '' && $this->google_secret != '') {
153 $this->conf[] = array('varname' => 'PRINTGCP_INFO', 'info' => 'GoogleAuthConfigured', 'type' => 'info');
154 $this->conf[] = array(
155 'varname' => 'PRINTGCP_TOKEN_ACCESS',
156 'info' => $access,
157 'type' => 'info',
158 'renew' => $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?state=userinfo_email,userinfo_profile,cloud_print&backtourl='.urlencode(DOL_URL_ROOT.'/printing/admin/printing.php?mode=setup&driver=printgcp'),
159 'delete' => ($storage->hasAccessToken($this->OAUTH_SERVICENAME_GOOGLE) ? $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?action=delete&token='.newToken().'&backtourl='.urlencode(DOL_URL_ROOT.'/printing/admin/printing.php?mode=setup&driver=printgcp') : '')
160 );
161 if ($token_ok) {
162 $expiredat = '';
163
164 $refreshtoken = $token->getRefreshToken();
165
166 $endoflife = $token->getEndOfLife();
167
168 if ($endoflife == $token::EOL_NEVER_EXPIRES) {
169 $expiredat = $langs->trans("Never");
170 } elseif ($endoflife == $token::EOL_UNKNOWN) {
171 $expiredat = $langs->trans("Unknown");
172 } else {
173 $expiredat = dol_print_date($endoflife, "dayhour");
174 }
175
176 $this->conf[] = array('varname' => 'TOKEN_REFRESH', 'info' => ((!empty($refreshtoken)) ? 'Yes' : 'No'), 'type' => 'info');
177 $this->conf[] = array('varname' => 'TOKEN_EXPIRED', 'info' => ($expire ? 'Yes' : 'No'), 'type' => 'info');
178 $this->conf[] = array('varname' => 'TOKEN_EXPIRE_AT', 'info' => ($expiredat), 'type' => 'info');
179 }
180 /*
181 if ($storage->hasAccessToken($this->OAUTH_SERVICENAME_GOOGLE)) {
182 $this->conf[] = array('varname'=>'PRINTGCP_AUTHLINK', 'link'=>$urlwithroot.'/core/modules/oauth/google_oauthcallback.php?backtourl='.urlencode(DOL_URL_ROOT.'/printing/admin/printing.php?mode=setup&driver=printgcp'), 'type'=>'authlink');
183 $this->conf[] = array('varname'=>'DELETE_TOKEN', 'link'=>$urlwithroot.'/core/modules/oauth/google_oauthcallback.php?action=delete&token='.newToken().'&backtourl='.urlencode(DOL_URL_ROOT.'/printing/admin/printing.php?mode=setup&driver=printgcp'), 'type'=>'delete');
184 } else {
185 $this->conf[] = array('varname'=>'PRINTGCP_AUTHLINK', 'link'=>$urlwithroot.'/core/modules/oauth/google_oauthcallback.php?backtourl='.urlencode(DOL_URL_ROOT.'/printing/admin/printing.php?mode=setup&driver=printgcp'), 'type'=>'authlink');
186 }*/
187 } else {
188 $this->conf[] = array('varname' => 'PRINTGCP_INFO', 'info' => 'GoogleAuthNotConfigured', 'type' => 'info');
189 }
190 }
191 // do not display submit button
192 $this->conf[] = array('enabled' => 0, 'type' => 'submit');
193 }
194
200 public function listAvailablePrinters()
201 {
202 global $conf, $langs;
203 $error = 0;
204 $langs->load('printing');
205
206 $html = '<tr class="liste_titre">';
207 $html .= '<td>'.$langs->trans('GCP_Name').'</td>';
208 $html .= '<td>'.$langs->trans('GCP_displayName').'</td>';
209 $html .= '<td>'.$langs->trans('GCP_Id').'</td>';
210 $html .= '<td>'.$langs->trans('GCP_OwnerName').'</td>';
211 $html .= '<td>'.$langs->trans('GCP_State').'</td>';
212 $html .= '<td>'.$langs->trans('GCP_connectionStatus').'</td>';
213 $html .= '<td>'.$langs->trans('GCP_Type').'</td>';
214 $html .= '<td class="center">'.$langs->trans("Select").'</td>';
215 $html .= '</tr>'."\n";
216 $list = $this->getlistAvailablePrinters();
217 //$html.= '<td><pre>'.print_r($list,true).'</pre></td>';
218 foreach ($list['available'] as $printer_det) {
219 $html .= '<tr class="oddeven">';
220 $html .= '<td>'.$printer_det['name'].'</td>';
221 $html .= '<td>'.$printer_det['displayName'].'</td>';
222 $html .= '<td>'.$printer_det['id'].'</td>'; // id to identify printer to use
223 $html .= '<td>'.$printer_det['ownerName'].'</td>';
224 $html .= '<td>'.$printer_det['status'].'</td>';
225 $html .= '<td>'.$langs->trans('STATE_'.$printer_det['connectionStatus']).'</td>';
226 $html .= '<td>'.$langs->trans('TYPE_'.$printer_det['type']).'</td>';
227 // Default
228 $html .= '<td class="center">';
229 if ($conf->global->PRINTING_GCP_DEFAULT == $printer_det['id']) {
230 $html .= img_picto($langs->trans("Default"), 'on');
231 } else {
232 $html .= '<a href="'.$_SERVER["PHP_SELF"].'?action=setvalue&token='.newToken().'&mode=test&varname=PRINTING_GCP_DEFAULT&driver=printgcp&value='.urlencode($printer_det['id']).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').'</a>';
233 }
234 $html .= '</td>';
235 $html .= '</tr>'."\n";
236 }
237 $this->resprint = $html;
238 return $error;
239 }
240
241
247 public function getlistAvailablePrinters()
248 {
249 global $conf;
250 $ret = array();
251
252 $keyforprovider = ''; // @FIXME
253
254 // Token storage
255 $storage = new DoliStorage($this->db, $conf, $keyforprovider);
256 // Setup the credentials for the requests
257 $credentials = new Credentials(
258 $this->google_id,
259 $this->google_secret,
260 DOL_MAIN_URL_ROOT.'/core/modules/oauth/google_oauthcallback.php'
261 );
262 $serviceFactory = new \OAuth\ServiceFactory();
263 $apiService = $serviceFactory->createService($this->OAUTH_SERVICENAME_GOOGLE, $credentials, $storage, array());
264 '@phan-var-force OAuth\OAuth2\Service\Google $apiService'; // createService is only ServiceInterface
265 // Check if we have auth token
266 $token_ok = true;
267 try {
268 $token = $storage->retrieveAccessToken($this->OAUTH_SERVICENAME_GOOGLE);
269 } catch (Exception $e) {
270 $this->errors[] = $e->getMessage();
271 $token_ok = false;
272 }
273 $expire = false;
274 // Is token expired or will token expire in the next 30 seconds
275 if ($token_ok) {
276 $expire = ($token->getEndOfLife() !== -9002 && $token->getEndOfLife() !== -9001 && time() > ($token->getEndOfLife() - 30));
277 }
278
279 // Token expired so we refresh it
280 if ($token_ok && $expire) {
281 try {
282 // il faut sauvegarder le refresh token car google ne le donne qu'une seule fois
283 $refreshtoken = $token->getRefreshToken();
284 $token = $apiService->refreshAccessToken($token);
285 $token->setRefreshToken($refreshtoken);
286 $storage->storeAccessToken($this->OAUTH_SERVICENAME_GOOGLE, $token);
287 } catch (Exception $e) {
288 $this->errors[] = $e->getMessage();
289 }
290 }
291 // Send a request with api
292 try {
293 $response = $apiService->request(self::PRINTERS_SEARCH_URL);
294 } catch (Exception $e) {
295 $this->errors[] = $e->getMessage();
296 print '<pre>'.print_r($e->getMessage(), true).'</pre>';
297 }
298 //print '<tr><td><pre>'.print_r($response, true).'</pre></td></tr>';
299 $responsedata = json_decode($response, true);
300 $printers = $responsedata['printers'];
301 // Check if we have printers?
302 if (is_array($printers) && count($printers) == 0) {
303 // We don't have printers so return blank array
304 $ret['available'] = array();
305 } else {
306 // We have printers so returns printers as array
307 $ret['available'] = $printers;
308 }
309 return $ret;
310 }
311
320 public function printFile($file, $module, $subdir = '')
321 {
322 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
323
324 global $conf, $user;
325 $error = 0;
326
327 $fileprint = $conf->{$module}->dir_output;
328 if ($subdir != '') {
329 $fileprint .= '/'.$subdir;
330 }
331 $fileprint .= '/'.$file;
332 $mimetype = dol_mimetype($fileprint);
333 $printer_id = '';
334 // select printer uri for module order, propal,...
335 $sql = "SELECT rowid, printer_id, copy FROM ".MAIN_DB_PREFIX."printing WHERE module='".$this->db->escape($module)."' AND driver='printgcp' AND userid=".((int) $user->id);
336 $result = $this->db->query($sql);
337 if ($result) {
338 $obj = $this->db->fetch_object($result);
339 if ($obj) {
340 $printer_id = $obj->printer_id;
341 } else {
342 if (getDolGlobalString('PRINTING_GCP_DEFAULT')) {
343 $printer_id = getDolGlobalString('PRINTING_GCP_DEFAULT');
344 } else {
345 $this->errors[] = 'NoDefaultPrinterDefined';
346 $error++;
347 return $error;
348 }
349 }
350 } else {
351 dol_print_error($this->db);
352 }
353
354 $ret = $this->sendPrintToPrinter($printer_id, $file, $fileprint, $mimetype);
355 $this->error = 'PRINTGCP: '.$ret['errormessage'];
356 if ($ret['status'] != 1) {
357 $error++;
358 }
359 return $error;
360 }
361
371 public function sendPrintToPrinter($printerid, $printjobtitle, $filepath, $contenttype)
372 {
373 global $conf;
374 // Check if printer id
375 if (empty($printerid)) {
376 return array('status' => 0, 'errorcode' => '', 'errormessage' => 'No provided printer ID');
377 }
378 // Open the file which needs to be print
379 $handle = fopen($filepath, "rb");
380 if (!$handle) {
381 return array('status' => 0, 'errorcode' => '', 'errormessage' => 'Could not read the file.');
382 }
383 // Read file content
384 $contents = fread($handle, filesize($filepath));
385 fclose($handle);
386 // Prepare post fields for sending print
387 $post_fields = array(
388 'printerid' => $printerid,
389 'title' => $printjobtitle,
390 'contentTransferEncoding' => 'base64',
391 'content' => base64_encode($contents), // encode file content as base64
392 'contentType' => $contenttype,
393 );
394
395 $keyforprovider = ''; // @FIXME
396
397 // Dolibarr Token storage
398 $storage = new DoliStorage($this->db, $conf, $keyforprovider);
399 // Setup the credentials for the requests
400 $credentials = new Credentials(
401 $this->google_id,
402 $this->google_secret,
403 DOL_MAIN_URL_ROOT.'/core/modules/oauth/google_oauthcallback.php?service=google'
404 );
405 $serviceFactory = new \OAuth\ServiceFactory();
406 $apiService = $serviceFactory->createService($this->OAUTH_SERVICENAME_GOOGLE, $credentials, $storage, array());
407 '@phan-var-force OAuth\OAuth2\Service\Google $apiService'; // createService is only ServiceInterface
408
409 // Check if we have auth token and refresh it
410 $token_ok = true;
411 try {
412 $token = $storage->retrieveAccessToken($this->OAUTH_SERVICENAME_GOOGLE);
413 } catch (Exception $e) {
414 $this->errors[] = $e->getMessage();
415 $token_ok = false;
416 }
417 if ($token_ok) {
418 try {
419 // il faut sauvegarder le refresh token car google ne le donne qu'une seule fois
420 $refreshtoken = $token->getRefreshToken();
421 $token = $apiService->refreshAccessToken($token);
422 $token->setRefreshToken($refreshtoken);
423 $storage->storeAccessToken($this->OAUTH_SERVICENAME_GOOGLE, $token);
424 } catch (Exception $e) {
425 $this->errors[] = $e->getMessage();
426 }
427 }
428
429 // Send a request with api
430 $response = json_decode($apiService->request(self::PRINT_URL, 'POST', $post_fields), true);
431 //print '<tr><td><pre>'.print_r($response, true).'</pre></td></tr>';
432 return array('status' => $response['success'], 'errorcode' => $response['errorCode'], 'errormessage' => $response['message']);
433 }
434
435
443 public function listJobs($module = null)
444 {
445 global $conf, $langs;
446
447 $error = 0;
448 $html = '';
449
450 $keyforprovider = ''; // @FIXME
451
452 // Token storage
453 $storage = new DoliStorage($this->db, $conf, $keyforprovider);
454 // Setup the credentials for the requests
455 $credentials = new Credentials(
456 $this->google_id,
457 $this->google_secret,
458 DOL_MAIN_URL_ROOT.'/core/modules/oauth/google_oauthcallback.php'
459 );
460 $serviceFactory = new \OAuth\ServiceFactory();
461 $apiService = $serviceFactory->createService($this->OAUTH_SERVICENAME_GOOGLE, $credentials, $storage, array());
462 '@phan-var-force OAuth\OAuth2\Service\Google $apiService'; // createService is only ServiceInterface
463 // Check if we have auth token
464 $token_ok = true;
465 try {
466 $token = $storage->retrieveAccessToken($this->OAUTH_SERVICENAME_GOOGLE);
467 } catch (Exception $e) {
468 $this->errors[] = $e->getMessage();
469 $token_ok = false;
470 $error++;
471 }
472 $expire = false;
473 // Is token expired or will token expire in the next 30 seconds
474 if ($token_ok) {
475 $expire = ($token->getEndOfLife() !== -9002 && $token->getEndOfLife() !== -9001 && time() > ($token->getEndOfLife() - 30));
476 }
477
478 // Token expired so we refresh it
479 if ($token_ok && $expire) {
480 try {
481 // il faut sauvegarder le refresh token car google ne le donne qu'une seule fois
482 $refreshtoken = $token->getRefreshToken();
483 $token = $apiService->refreshAccessToken($token);
484 $token->setRefreshToken($refreshtoken);
485 $storage->storeAccessToken($this->OAUTH_SERVICENAME_GOOGLE, $token);
486 } catch (Exception $e) {
487 $this->errors[] = $e->getMessage();
488 $error++;
489 }
490 }
491 // Getting Jobs
492 // Send a request with api
493 try {
494 $response = $apiService->request(self::PRINTERS_GET_JOBS);
495 } catch (Exception $e) {
496 $this->errors[] = $e->getMessage();
497 $error++;
498 }
499 $responsedata = json_decode($response, true);
500 //$html .= '<pre>'.print_r($responsedata,true).'</pre>';
501 $html .= '<div class="div-table-responsive">';
502 $html .= '<table width="100%" class="noborder">';
503 $html .= '<tr class="liste_titre">';
504 $html .= '<td>'.$langs->trans("Id").'</td>';
505 $html .= '<td>'.$langs->trans("Date").'</td>';
506 $html .= '<td>'.$langs->trans("Owner").'</td>';
507 $html .= '<td>'.$langs->trans("Printer").'</td>';
508 $html .= '<td>'.$langs->trans("Filename").'</td>';
509 $html .= '<td>'.$langs->trans("Status").'</td>';
510 $html .= '<td>'.$langs->trans("Cancel").'</td>';
511 $html .= '</tr>'."\n";
512
513 $jobs = $responsedata['jobs'];
514 //$html .= '<pre>'.print_r($jobs['0'],true).'</pre>';
515 if (is_array($jobs)) {
516 foreach ($jobs as $value) {
517 $html .= '<tr class="oddeven">';
518 $html .= '<td>'.$value['id'].'</td>';
519 $dates = dol_print_date((int) substr($value['createTime'], 0, 10), 'dayhour');
520 $html .= '<td>'.$dates.'</td>';
521 $html .= '<td>'.$value['ownerId'].'</td>';
522 $html .= '<td>'.$value['printerName'].'</td>';
523 $html .= '<td>'.$value['title'].'</td>';
524 $html .= '<td>'.$value['status'].'</td>';
525 $html .= '<td>&nbsp;</td>';
526 $html .= '</tr>';
527 }
528 } else {
529 $html .= '<tr class="oddeven">';
530 $html .= '<td colspan="7" class="opacitymedium">'.$langs->trans("None").'</td>';
531 $html .= '</tr>';
532 }
533 $html .= '</table>';
534 $html .= '</div>';
535
536 $this->resprint = $html;
537
538 return $error;
539 }
540}
Parent class of emailing target selectors modules.
Class to provide printing with Google Cloud Print.
listJobs($module=null)
List jobs print.
__construct($db)
Constructor.
listAvailablePrinters()
Return list of available printers.
printFile($file, $module, $subdir='')
Print selected file.
getlistAvailablePrinters()
Return list of available printers.
sendPrintToPrinter($printerid, $printjobtitle, $filepath, $contenttype)
Sends document to the printer.
dol_mimetype($file, $default='application/octet-stream', $mode=0)
Return MIME type of a file from its name with extension.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
newToken()
Return the value of token currently saved into session with name 'newtoken'.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
conf($dolibarr_main_document_root)
Load conf file (file must exists)
Definition inc.php:420