Skip to content
Snippets Groups Projects
Hub.php 8.37 KiB
<?php
/**
 * Copyright (c) 2012-2014, Agence Française Informatique (AFI). All rights reserved.
 *
 * BOKEH is free software; you can redistribute it and/or modify
 * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
 * the Free Software Foundation.
 *
 * There are special exceptions to the terms and conditions of the AGPL as it
 * is applied to this software (see README file).
 *
 * BOKEH is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
 *
 * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
 * along with BOKEH; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
 */


class Class_WebService_BibNumerique_Dilicom_Hub extends Class_WebService_Abstract {
  use
    Trait_TimeSource,
    Trait_Translator;

  const STATUS_OK = 'OK';

  protected $_now;


  public function getLoanStatus($album) {
    $content = json_decode($this->dilicomCall('getLoanStatus',
                                              ['orderLineId[0]' => $this->getOrderLineId($album)]));

    return $content;
  }


  public function updateStatus($album) {
    $content = $this->getLoanStatus($album);

    if (isset($content->loanResponseLine[0])
        && ($simultaneous_users_remaining = $content->loanResponseLine[0]->nus1)) {
      $item = $album->getItems()[0];
      $item->setLoanCount($album->getUsageConstraints()->getLoanMaxNumberOfUsers() - $simultaneous_users_remaining);
      $item->setQuantity($album->getUsageConstraints()->getLoanQuantity() - $content->loanResponseLine[0]->nta);
      $item->save();
    }

    return $content;
  }


  /** @return int number of updated loans */
  public function updateLoansReturnDate($loans) {
    if (!$loans)
      return 0;

    $updated = 0;
    // pnb service max 20 ids per request
    foreach(array_chunk($loans, 20) as $page)
      $updated += $this->_updateLoansPageReturnDate($page);

    return $updated;
  }


  /** @return int number of updated loans */
  protected function _updateLoansPageReturnDate($page) {
    if ((!$response = $this->_getEndedLoans($page))
        || !$this->_isResponseOk($response))
      return 0;

    $mapping = [];
    foreach($page as $loan)
      $mapping[$loan->getId()] = $loan;

    $updated = 0;
    foreach($response->loanEndedResponseLine as $line)
      if (array_key_exists($line->loanId, $mapping)) {
        $mapping[$line->loanId]
          ->setExpectedReturnDate($line->returnDate)
          ->save();
        $updated++;
      }

    return $updated;
  }


  protected function _isResponseOk($response) {
    return static::STATUS_OK == $response->returnStatus;
  }


  protected function _getEndedLoans($loans) {
    if (!$loans)
      return;

    $params = [];
    $i = 0;
    foreach($loans as $loan) {
      $params['loanId[' . $i . ']'] = $loan->getId();
      $i++;
    }

    return json_decode($this->dilicomCall('getEndedLoans', $params));
  }


  public function loanBook($album) {
    $user = Class_Users::getIdentity();
    $this->_now = $this->getCurrentTime();

    $loan = $user->getPNBLoans()
                 ->detect(
                          function($item) use($album) {
                            return $item->getRecordOriginId() == $album->getIdOrigine();
                          });

    if ($loan
        && (strtotime($loan->getExpectedReturnDate()) > $this->_now))
      return (object) ['link' => (object) ['url' => $loan->getLoanLink()],
                       'returnMessage' => []];

    if (!$album->getUsageConstraints()->hasSimultaneousLoanRemaining())
      return (object) ['returnMessage' => [$this->_('Emprunt impossible. Le nombre d\'emprunts simultanés est atteint.')]];

    if (!$album->getUsageConstraints()->hasAvailableQuantity())
      return (object) ['returnMessage' => [$this->_('Emprunt impossible. Le nombre d\'emprunts disponible est épuisé.')]];

    if (!$album->getUsageConstraints()->isAValidOffer())
      return (object) ['returnMessage' => [$this->_('Emprunt impossible. L\'emprunt du document n\'est plus disponible.')]];

    $quota = (int)Class_AdminVar::getValueOrDefault('DILICOM_PNB_MAX_LOAN_PER_USER');
    if ($user->getPNBLoans()->count() >= $quota)
      return (object) ['returnMessage' => [$this->_('Emprunt impossible. Vous avez atteint votre quota de %s emprunts.', $quota)]];

    $loan = Class_Loan_Pnb::newInstance(['subscriber_id' => $user->getIdabon(),
                                         'user_id' => $user->getId(),
                                         'loan_date' => $this->startDate(),
                                         'expected_return_date' => $this->endLoanDate($album),
                                         'record_origin_id' => $album->getIdOrigine()]);
    $loan->save();

    $response = $this->dilicomCall('loanBook',
                                   ['orderLineId' => $this->getOrderLineId($album),
                                    'accessMedium' => 'DOWNLOAD',
                                    'glnColl' => Class_AdminVar::get('DILICOM_PNB_GLN_COLLECTIVITE'),
                                    'loanerColl' => $user->getBibGLN(),
                                    'localization' => 'EX_SITU',
                                    'loanEndDate' => urlencode($this->endLoanDate($album)),
                                    'ean13' => $album->getISBN(),
                                    'loanId' =>  $loan->getId(),
                                   ]);

    $content = json_decode($response);

    $loan->setLoanLink($content->link->url)->save();

    if($content->returnMessage)
      $loan->delete();

    return $content;
  }


  public function consultBook($album, $ip_address, $user) {
    $this->_now = $this->getCurrentTime();
    return $this->dilicomCall('consultBook',
                              ['orderLineId' => $this->getOrderLineId($album),
                               'accessMedium' => 'STREAMING',
                               'localization' => 'IN_SITU',
                               'consultEndDate' => urlencode($this->endConsultDate()),
                               'ean13' => $album->getISBN(),
                               'ipAddress' => $ip_address,
                               'glnColl' => Class_AdminVar::get('DILICOM_PNB_GLN_COLLECTIVITE'),
                               'loanerColl' => $user->getBibGLN(),
                               'loanId' =>  implode('',
                                                    [base_convert($this->getTimeSource()->time(), 10, 36),
                                                     Class_Users::currentUserId(),
                                                     $album->getId()])
                              ]);
  }


  public function declareIp($ips = []) {
    return $this->dilicomCall('declareIp', $this->buildIps($ips));
  }


  public function getOrderLineId($album) {
    return $album->getUsageConstraints()->getLoanOrderLineId();
  }


  public function endLoanDate($album) {
    return $this->iso8601($this->_now +
                          $album->getUsageConstraints()->getLoanDuration() * 3600 * 24);
  }


  public function endConsultDate() {
    return $this->iso8601($this->_now + 3600);
  }

  public function startDate() {
    return $this->iso8601($this->_now);
  }


  protected function iso8601($timestamp) {
    return date(DATE_ISO8601, $timestamp);
  }


  protected function dilicomCall($service, $params) {
    static::getHttpClient()
      ->setAuth(Class_AdminVar::get('DILICOM_PNB_GLN_COLLECTIVITE'),
                Class_AdminVar::get('DILICOM_PNB_PWD_COLLECTIVITE'));

    return $this->httpGet($this->buildUrl($service, $params));
  }


  protected function buildUrl($service, $params) {
    $params = array_merge(['glnContractor' => Class_AdminVar::get('DILICOM_PNB_GLN_CONTRACTOR')],
                          $params);

    $parts = [];
    foreach($params as $key => $value) {
      $parts[] = $key . '=' . $value;
    }

    return $this->getDilicomUrl() . $service . '?' . implode('&', $parts);
  }


  protected function getDilicomUrl() {
    return Class_AdminVar::get('DILICOM_PNB_SERVER_URL') . '/v2/pnb-numerique/json/';
  }


  protected function buildIps($ips) {
    $ips_param = [];
    for($i = 0; $i < count($ips); $i++) {
      $ips_param['ips[' . $i . ']'] = $ips[$i];
    }
    return $ips_param;
  }
}
?>