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