dolibarr  13.0.2
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  $this->google_id = $conf->global->OAUTH_GOOGLE_ID;
120  $this->google_secret = $conf->global->OAUTH_GOOGLE_SECRET;
121  // Token storage
122  $storage = new DoliStorage($this->db, $this->conf);
123  //$storage->clearToken($this->OAUTH_SERVICENAME_GOOGLE);
124  // Setup the credentials for the requests
125  $credentials = new Credentials(
126  $this->google_id,
127  $this->google_secret,
128  $urlwithroot.'/core/modules/oauth/google_oauthcallback.php'
129  );
130  $access = ($storage->hasAccessToken($this->OAUTH_SERVICENAME_GOOGLE) ? 'HasAccessToken' : 'NoAccessToken');
131  $serviceFactory = new \OAuth\ServiceFactory();
132  $apiService = $serviceFactory->createService($this->OAUTH_SERVICENAME_GOOGLE, $credentials, $storage, array());
133  $token_ok = true;
134  try {
135  $token = $storage->retrieveAccessToken($this->OAUTH_SERVICENAME_GOOGLE);
136  } catch (Exception $e) {
137  $this->errors[] = $e->getMessage();
138  $token_ok = false;
139  }
140  //var_dump($this->errors);exit;
141 
142  $expire = false;
143  // Is token expired or will token expire in the next 30 seconds
144  if ($token_ok) {
145  $expire = ($token->getEndOfLife() !== -9002 && $token->getEndOfLife() !== -9001 && time() > ($token->getEndOfLife() - 30));
146  }
147 
148  // Token expired so we refresh it
149  if ($token_ok && $expire) {
150  try {
151  // il faut sauvegarder le refresh token car google ne le donne qu'une seule fois
152  $refreshtoken = $token->getRefreshToken();
153  $token = $apiService->refreshAccessToken($token);
154  $token->setRefreshToken($refreshtoken);
155  $storage->storeAccessToken($this->OAUTH_SERVICENAME_GOOGLE, $token);
156  } catch (Exception $e) {
157  $this->errors[] = $e->getMessage();
158  }
159  }
160  if ($this->google_id != '' && $this->google_secret != '') {
161  $this->conf[] = array('varname'=>'PRINTGCP_INFO', 'info'=>'GoogleAuthConfigured', 'type'=>'info');
162  $this->conf[] = array(
163  'varname'=>'PRINTGCP_TOKEN_ACCESS',
164  'info'=>$access,
165  'type'=>'info',
166  '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'),
167  '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') : '')
168  );
169  if ($token_ok) {
170  $expiredat = '';
171 
172  $refreshtoken = $token->getRefreshToken();
173 
174  $endoflife = $token->getEndOfLife();
175 
176  if ($endoflife == $token::EOL_NEVER_EXPIRES)
177  {
178  $expiredat = $langs->trans("Never");
179  } elseif ($endoflife == $token::EOL_UNKNOWN)
180  {
181  $expiredat = $langs->trans("Unknown");
182  } else {
183  $expiredat = dol_print_date($endoflife, "dayhour");
184  }
185 
186  $this->conf[] = array('varname'=>'TOKEN_REFRESH', 'info'=>((!empty($refreshtoken)) ? 'Yes' : 'No'), 'type'=>'info');
187  $this->conf[] = array('varname'=>'TOKEN_EXPIRED', 'info'=>($expire ? 'Yes' : 'No'), 'type'=>'info');
188  $this->conf[] = array('varname'=>'TOKEN_EXPIRE_AT', 'info'=>($expiredat), 'type'=>'info');
189  }
190  /*
191  if ($storage->hasAccessToken($this->OAUTH_SERVICENAME_GOOGLE)) {
192  $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');
193  $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');
194  } else {
195  $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');
196  }*/
197  } else {
198  $this->conf[] = array('varname'=>'PRINTGCP_INFO', 'info'=>'GoogleAuthNotConfigured', 'type'=>'info');
199  }
200  }
201  // do not display submit button
202  $this->conf[] = array('enabled'=>0, 'type'=>'submit');
203  }
204 
210  public function listAvailablePrinters()
211  {
212  global $conf, $langs;
213  $error = 0;
214  $langs->load('printing');
215 
216  $html = '<tr class="liste_titre">';
217  $html .= '<td>'.$langs->trans('GCP_Name').'</td>';
218  $html .= '<td>'.$langs->trans('GCP_displayName').'</td>';
219  $html .= '<td>'.$langs->trans('GCP_Id').'</td>';
220  $html .= '<td>'.$langs->trans('GCP_OwnerName').'</td>';
221  $html .= '<td>'.$langs->trans('GCP_State').'</td>';
222  $html .= '<td>'.$langs->trans('GCP_connectionStatus').'</td>';
223  $html .= '<td>'.$langs->trans('GCP_Type').'</td>';
224  $html .= '<td class="center">'.$langs->trans("Select").'</td>';
225  $html .= '</tr>'."\n";
226  $list = $this->getlistAvailablePrinters();
227  //$html.= '<td><pre>'.print_r($list,true).'</pre></td>';
228  foreach ($list['available'] as $printer_det)
229  {
230  $html .= '<tr class="oddeven">';
231  $html .= '<td>'.$printer_det['name'].'</td>';
232  $html .= '<td>'.$printer_det['displayName'].'</td>';
233  $html .= '<td>'.$printer_det['id'].'</td>'; // id to identify printer to use
234  $html .= '<td>'.$printer_det['ownerName'].'</td>';
235  $html .= '<td>'.$printer_det['status'].'</td>';
236  $html .= '<td>'.$langs->trans('STATE_'.$printer_det['connectionStatus']).'</td>';
237  $html .= '<td>'.$langs->trans('TYPE_'.$printer_det['type']).'</td>';
238  // Defaut
239  $html .= '<td class="center">';
240  if ($conf->global->PRINTING_GCP_DEFAULT == $printer_det['id'])
241  {
242  $html .= img_picto($langs->trans("Default"), 'on');
243  } else $html .= '<a href="'.$_SERVER["PHP_SELF"].'?action=setvalue&amp;token='.newToken().'&amp;mode=test&amp;varname=PRINTING_GCP_DEFAULT&amp;driver=printgcp&amp;value='.urlencode($printer_det['id']).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').'</a>';
244  $html .= '</td>';
245  $html .= '</tr>'."\n";
246  }
247  $this->resprint = $html;
248  return $error;
249  }
250 
251 
257  public function getlistAvailablePrinters()
258  {
259  $ret = array();
260  // Token storage
261  $storage = new DoliStorage($this->db, $this->conf);
262  // Setup the credentials for the requests
263  $credentials = new Credentials(
264  $this->google_id,
265  $this->google_secret,
266  DOL_MAIN_URL_ROOT.'/core/modules/oauth/google_oauthcallback.php'
267  );
268  $serviceFactory = new \OAuth\ServiceFactory();
269  $apiService = $serviceFactory->createService($this->OAUTH_SERVICENAME_GOOGLE, $credentials, $storage, array());
270  // Check if we have auth token
271  $token_ok = true;
272  try {
273  $token = $storage->retrieveAccessToken($this->OAUTH_SERVICENAME_GOOGLE);
274  } catch (Exception $e) {
275  $this->errors[] = $e->getMessage();
276  $token_ok = false;
277  }
278  $expire = false;
279  // Is token expired or will token expire in the next 30 seconds
280  if ($token_ok) {
281  $expire = ($token->getEndOfLife() !== -9002 && $token->getEndOfLife() !== -9001 && time() > ($token->getEndOfLife() - 30));
282  }
283 
284  // Token expired so we refresh it
285  if ($token_ok && $expire) {
286  try {
287  // il faut sauvegarder le refresh token car google ne le donne qu'une seule fois
288  $refreshtoken = $token->getRefreshToken();
289  $token = $apiService->refreshAccessToken($token);
290  $token->setRefreshToken($refreshtoken);
291  $storage->storeAccessToken($this->OAUTH_SERVICENAME_GOOGLE, $token);
292  } catch (Exception $e) {
293  $this->errors[] = $e->getMessage();
294  }
295  }
296  // Send a request with api
297  try {
298  $response = $apiService->request(self::PRINTERS_SEARCH_URL);
299  } catch (Exception $e) {
300  $this->errors[] = $e->getMessage();
301  print '<pre>'.print_r($e->getMessage(), true).'</pre>';
302  }
303  //print '<tr><td><pre>'.print_r($response, true).'</pre></td></tr>';
304  $responsedata = json_decode($response, true);
305  $printers = $responsedata['printers'];
306  // Check if we have printers?
307  if (is_array($printers) && count($printers) == 0) {
308  // We dont have printers so return blank array
309  $ret['available'] = array();
310  } else {
311  // We have printers so returns printers as array
312  $ret['available'] = $printers;
313  }
314  return $ret;
315  }
316 
325  public function printFile($file, $module, $subdir = '')
326  {
327  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
328 
329  global $conf, $user;
330  $error = 0;
331 
332  $fileprint = $conf->{$module}->dir_output;
333  if ($subdir != '') {
334  $fileprint .= '/'.$subdir;
335  }
336  $fileprint .= '/'.$file;
337  $mimetype = dol_mimetype($fileprint);
338  // select printer uri for module order, propal,...
339  $sql = "SELECT rowid, printer_id, copy FROM ".MAIN_DB_PREFIX."printing WHERE module='".$this->db->escape($module)."' AND driver='printgcp' AND userid=".$user->id;
340  $result = $this->db->query($sql);
341  if ($result)
342  {
343  $obj = $this->db->fetch_object($result);
344  if ($obj)
345  {
346  $printer_id = $obj->printer_id;
347  } else {
348  if (!empty($conf->global->PRINTING_GCP_DEFAULT))
349  {
350  $printer_id = $conf->global->PRINTING_GCP_DEFAULT;
351  } else {
352  $this->errors[] = 'NoDefaultPrinterDefined';
353  $error++;
354  return $error;
355  }
356  }
357  } else {
358  dol_print_error($this->db);
359  }
360 
361  $ret = $this->sendPrintToPrinter($printer_id, $file, $fileprint, $mimetype);
362  $this->error = 'PRINTGCP: '.$ret['errormessage'];
363  if ($ret['status'] != 1) {
364  $error++;
365  }
366  return $error;
367  }
368 
378  public function sendPrintToPrinter($printerid, $printjobtitle, $filepath, $contenttype)
379  {
380  // Check if printer id
381  if (empty($printerid)) {
382  return array('status' =>0, 'errorcode' =>'', 'errormessage'=>'No provided printer ID');
383  }
384  // Open the file which needs to be print
385  $handle = fopen($filepath, "rb");
386  if (!$handle) {
387  return array('status' =>0, 'errorcode' =>'', 'errormessage'=>'Could not read the file.');
388  }
389  // Read file content
390  $contents = fread($handle, filesize($filepath));
391  fclose($handle);
392  // Prepare post fields for sending print
393  $post_fields = array(
394  'printerid' => $printerid,
395  'title' => $printjobtitle,
396  'contentTransferEncoding' => 'base64',
397  'content' => base64_encode($contents), // encode file content as base64
398  'contentType' => $contenttype,
399  );
400  // Dolibarr Token storage
401  $storage = new DoliStorage($this->db, $this->conf);
402  // Setup the credentials for the requests
403  $credentials = new Credentials(
404  $this->google_id,
405  $this->google_secret,
406  DOL_MAIN_URL_ROOT.'/core/modules/oauth/google_oauthcallback.php?service=google'
407  );
408  $serviceFactory = new \OAuth\ServiceFactory();
409  $apiService = $serviceFactory->createService($this->OAUTH_SERVICENAME_GOOGLE, $credentials, $storage, array());
410 
411  // Check if we have auth token and refresh it
412  $token_ok = true;
413  try {
414  $token = $storage->retrieveAccessToken($this->OAUTH_SERVICENAME_GOOGLE);
415  } catch (Exception $e) {
416  $this->errors[] = $e->getMessage();
417  $token_ok = false;
418  }
419  if ($token_ok) {
420  try {
421  // il faut sauvegarder le refresh token car google ne le donne qu'une seule fois
422  $refreshtoken = $token->getRefreshToken();
423  $token = $apiService->refreshAccessToken($token);
424  $token->setRefreshToken($refreshtoken);
425  $storage->storeAccessToken($this->OAUTH_SERVICENAME_GOOGLE, $token);
426  } catch (Exception $e) {
427  $this->errors[] = $e->getMessage();
428  }
429  }
430 
431  // Send a request with api
432  $response = json_decode($apiService->request(self::PRINT_URL, 'POST', $post_fields), true);
433  //print '<tr><td><pre>'.print_r($response, true).'</pre></td></tr>';
434  return array('status' => $response['success'], 'errorcode' => $response['errorCode'], 'errormessage' => $response['message']);
435  }
436 
437 
443  public function listJobs()
444  {
445  global $conf, $langs;
446 
447  $error = 0;
448  $html = '';
449  // Token storage
450  $storage = new DoliStorage($this->db, $this->conf);
451  // Setup the credentials for the requests
452  $credentials = new Credentials(
453  $this->google_id,
454  $this->google_secret,
455  DOL_MAIN_URL_ROOT.'/core/modules/oauth/google_oauthcallback.php'
456  );
457  $serviceFactory = new \OAuth\ServiceFactory();
458  $apiService = $serviceFactory->createService($this->OAUTH_SERVICENAME_GOOGLE, $credentials, $storage, array());
459  // Check if we have auth token
460  $token_ok = true;
461  try {
462  $token = $storage->retrieveAccessToken($this->OAUTH_SERVICENAME_GOOGLE);
463  } catch (Exception $e) {
464  $this->errors[] = $e->getMessage();
465  $token_ok = false;
466  $error++;
467  }
468  $expire = false;
469  // Is token expired or will token expire in the next 30 seconds
470  if ($token_ok) {
471  $expire = ($token->getEndOfLife() !== -9002 && $token->getEndOfLife() !== -9001 && time() > ($token->getEndOfLife() - 30));
472  }
473 
474  // Token expired so we refresh it
475  if ($token_ok && $expire) {
476  try {
477  // il faut sauvegarder le refresh token car google ne le donne qu'une seule fois
478  $refreshtoken = $token->getRefreshToken();
479  $token = $apiService->refreshAccessToken($token);
480  $token->setRefreshToken($refreshtoken);
481  $storage->storeAccessToken($this->OAUTH_SERVICENAME_GOOGLE, $token);
482  } catch (Exception $e) {
483  $this->errors[] = $e->getMessage();
484  $error++;
485  }
486  }
487  // Getting Jobs
488  // Send a request with api
489  try {
490  $response = $apiService->request(self::PRINTERS_GET_JOBS);
491  } catch (Exception $e) {
492  $this->errors[] = $e->getMessage();
493  $error++;
494  }
495  $responsedata = json_decode($response, true);
496  //$html .= '<pre>'.print_r($responsedata,true).'</pre>';
497  $html .= '<div class="div-table-responsive">';
498  $html .= '<table width="100%" class="noborder">';
499  $html .= '<tr class="liste_titre">';
500  $html .= '<td>'.$langs->trans("Id").'</td>';
501  $html .= '<td>'.$langs->trans("Date").'</td>';
502  $html .= '<td>'.$langs->trans("Owner").'</td>';
503  $html .= '<td>'.$langs->trans("Printer").'</td>';
504  $html .= '<td>'.$langs->trans("Filename").'</td>';
505  $html .= '<td>'.$langs->trans("Status").'</td>';
506  $html .= '<td>'.$langs->trans("Cancel").'</td>';
507  $html .= '</tr>'."\n";
508 
509  $jobs = $responsedata['jobs'];
510  //$html .= '<pre>'.print_r($jobs['0'],true).'</pre>';
511  if (is_array($jobs)) {
512  foreach ($jobs as $value) {
513  $html .= '<tr class="oddeven">';
514  $html .= '<td>'.$value['id'].'</td>';
515  $dates = dol_print_date((int) substr($value['createTime'], 0, 10), 'dayhour');
516  $html .= '<td>'.$dates.'</td>';
517  $html .= '<td>'.$value['ownerId'].'</td>';
518  $html .= '<td>'.$value['printerName'].'</td>';
519  $html .= '<td>'.$value['title'].'</td>';
520  $html .= '<td>'.$value['status'].'</td>';
521  $html .= '<td>&nbsp;</td>';
522  $html .= '</tr>';
523  }
524  } else {
525  $html .= '<tr class="oddeven">';
526  $html .= '<td colspan="7" class="opacitymedium">'.$langs->trans("None").'</td>';
527  $html .= '</tr>';
528  }
529  $html .= '</table>';
530  $html .= '</div>';
531 
532  $this->resprint = $html;
533 
534  return $error;
535  }
536 }
sendPrintToPrinter($printerid, $printjobtitle, $filepath, $contenttype)
Sends document to the printer.
conf($dolibarr_main_document_root)
Load conf file (file must exists)
Definition: inc.php:262
printFile($file, $module, $subdir= '')
Print selected file.
listJobs()
List jobs print.
Parent class of emailing target selectors modules.
$conf db
API class for accounts.
Definition: inc.php:54
dol_mimetype($file, $default= 'application/octet-stream', $mode=0)
Return mime type of a file.
listAvailablePrinters()
Return list of available printers.
img_picto($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt= '', $morecss= '', $marginleftonlyshort=2)
Show picto whatever it&#39;s its name (generic function)
Class to provide printing with Google Cloud Print.
print
Draft customers invoices.
Definition: index.php:89
dol_print_date($time, $format= '', $tzoutput= 'auto', $outputlangs= '', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_print_error($db= '', $error= '', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
newToken()
Return the value of token currently saved into session with name &#39;newtoken&#39;.
getlistAvailablePrinters()
Return list of available printers.
__construct($db)
Constructor.