$perm = $options->getFilePermission();
if ($umask !== false && $perm !== false) {
$perm = $perm & ~$umask;
}
ErrorHandler::start();
// if locking and non blocking is enabled -> file_put_contents can't used
if ($locking && $nonBlocking) {
$umask = ($umask !== false) ? umask($umask) : false;
$fp = fopen($file, 'cb');
if ($umask) {
umask($umask);
}
if (! $fp) {
$err = ErrorHandler::stop();
throw new Exception\RuntimeException("Error opening file '{$file}'", 0, $err);
}
if ($perm !== false && ! chmod($file, $perm)) {
fclose($fp);
$oct = decoct($perm);
$err = ErrorHandler::stop();
throw new Exception\RuntimeException("chmod('{$file}', 0{$oct}) failed", 0, $err);
}
if (! flock($fp, LOCK_EX | LOCK_NB, $wouldblock)) {
fclose($fp);
$err = ErrorHandler::stop();
if ($wouldblock) {
return;
} else {
throw new Exception\RuntimeException("Error locking file '{$file}'", 0, $err);
}
}
if (fwrite($fp, $data) === false) {
}
$options = $this->getOptions();
$locking = $options->getFileLocking();
$nonBlocking = $locking && $nonBlocking;
$wouldblock = null;
$umask = $options->getUmask();
$perm = $options->getFilePermission();
if ($umask !== false && $perm !== false) {
$perm = $perm & ~$umask;
}
ErrorHandler::start();
// if locking and non blocking is enabled -> file_put_contents can't used
if ($locking && $nonBlocking) {
$umask = ($umask !== false) ? umask($umask) : false;
$fp = fopen($file, 'cb');
if ($umask) {
umask($umask);
}
if (! $fp) {
$err = ErrorHandler::stop();
throw new Exception\RuntimeException("Error opening file '{$file}'", 0, $err);
}
if ($perm !== false && ! chmod($file, $perm)) {
fclose($fp);
$oct = decoct($perm);
$err = ErrorHandler::stop();
throw new Exception\RuntimeException("chmod('{$file}', 0{$oct}) failed", 0, $err);
}
if (! flock($fp, LOCK_EX | LOCK_NB, $wouldblock)) {
fclose($fp);
$err = ErrorHandler::stop();
}
$options = $this->getOptions();
$locking = $options->getFileLocking();
$nonBlocking = $locking && $nonBlocking;
$wouldblock = null;
$umask = $options->getUmask();
$perm = $options->getFilePermission();
if ($umask !== false && $perm !== false) {
$perm = $perm & ~$umask;
}
ErrorHandler::start();
// if locking and non blocking is enabled -> file_put_contents can't used
if ($locking && $nonBlocking) {
$umask = ($umask !== false) ? umask($umask) : false;
$fp = fopen($file, 'cb');
if ($umask) {
umask($umask);
}
if (! $fp) {
$err = ErrorHandler::stop();
throw new Exception\RuntimeException("Error opening file '{$file}'", 0, $err);
}
if ($perm !== false && ! chmod($file, $perm)) {
fclose($fp);
$oct = decoct($perm);
$err = ErrorHandler::stop();
throw new Exception\RuntimeException("chmod('{$file}', 0{$oct}) failed", 0, $err);
}
if (! flock($fp, LOCK_EX | LOCK_NB, $wouldblock)) {
fclose($fp);
$err = ErrorHandler::stop();
return parent::replaceItems($keyValuePairs);
}
/**
* Internal method to store an item.
*
* @param string $normalizedKey
* @param mixed $value
* @return bool
* @throws Exception\ExceptionInterface
*/
protected function internalSetItem(& $normalizedKey, & $value)
{
$filespec = $this->getFileSpec($normalizedKey);
$file = $this->formatFilename($filespec);
$this->prepareDirectoryStructure($filespec);
// write data in non-blocking mode
$wouldblock = null;
$this->putFileContent($file, $value, true, $wouldblock);
// delete related tag file (if present)
$this->unlink($this->formatTagFilename($filespec));
// Retry writing data in blocking mode if it was blocked before
if ($wouldblock) {
$this->putFileContent($file, $value);
}
return true;
}
/**
* Internal method to store multiple items.
*
* @param array $normalizedKeyValuePairs
* @return array Array of not stored keys
* @throws Exception\ExceptionInterface
*/
protected function internalSetItems(array & $normalizedKeyValuePairs)
* @triggers setItem.exception(ExceptionEvent)
*/
public function setItem($key, $value)
{
if (! $this->getOptions()->getWritable()) {
return false;
}
$this->normalizeKey($key);
$args = new ArrayObject([
'key' => & $key,
'value' => & $value,
]);
try {
$eventRs = $this->triggerPre(__FUNCTION__, $args);
$result = $eventRs->stopped()
? $eventRs->last()
: $this->internalSetItem($args['key'], $args['value']);
return $this->triggerPost(__FUNCTION__, $args, $result);
} catch (\Exception $e) {
$result = false;
return $this->triggerException(__FUNCTION__, $args, $result, $e);
}
}
/**
* Internal method to store an item.
*
* @param string $normalizedKey
* @param mixed $value
* @return bool
* @throws Exception\ExceptionInterface
*/
abstract protected function internalSetItem(& $normalizedKey, & $value);
/**
* Store multiple items.
/**
* Store an item.
*
* @param string $key
* @param mixed $value
* @return bool
* @throws Exception\ExceptionInterface
*
* @triggers setItem.pre(PreEvent)
* @triggers setItem.post(PostEvent)
* @triggers setItem.exception(ExceptionEvent)
*/
public function setItem($key, $value)
{
$options = $this->getOptions();
if ($options->getWritable() && $options->getClearStatCache()) {
clearstatcache();
}
return parent::setItem($key, $value);
}
/**
* Store multiple items.
*
* @param array $keyValuePairs
* @return array Array of not stored keys
* @throws Exception\ExceptionInterface
*
* @triggers setItems.pre(PreEvent)
* @triggers setItems.post(PostEvent)
* @triggers setItems.exception(ExceptionEvent)
*/
public function setItems(array $keyValuePairs)
{
$options = $this->getOptions();
if ($options->getWritable() && $options->getClearStatCache()) {
clearstatcache();
}
* Data is cached for up to $this->cacheLifetime seconds.
*
* @param string $key Cache entry key
* @param mixed $entry Entry to be cached
* @param int $lifetime Optional lifetime for the entry in seconds
*
* @return void
*/
protected function putCachedData($key, $entry, $lifetime = null)
{
// Don't write to cache if we don't have a cache!
if (null === $this->cache) {
return;
}
$item = [
'time' => time(),
'lifetime' => $lifetime,
'entry' => $entry,
];
$this->cache->setItem($this->getCacheKey($key), $item);
}
/**
* Helper function for removing cached data.
*
* @param string $key Cache entry key
*
* @return void
*/
protected function removeCachedData($key)
{
// Don't write to cache if we don't have a cache!
if (null === $this->cache) {
return;
}
$this->cache->removeItem($this->getCacheKey($key));
}
}
$url = $this->config['Catalog']['host'] . '/v1/oauth/token';
try {
$token = $this->getNewOAuth2Token(
$url,
$this->config['Catalog']['clientId'],
$this->config['Catalog']['clientSecret'],
$this->config['Catalog']['grantType'] ?? 'client_credentials'
);
} catch (AuthTokenException $exception) {
throw new ILSException(
'Problem with Koha REST API: ' . $exception->getMessage()
);
}
$this->putCachedData(
$cacheKey,
$token->getHeaderValue(),
$token->getExpiresIn()
);
return $token->getHeaderValue();
}
/**
* Get Item Statuses
*
* This is responsible for retrieving the status information of a certain
* record.
*
* @param string $id The record id to retrieve the holdings for
* @param array $patron Patron information, if available
*
* @return array An associative array with the following keys:
* id, availability (boolean), status, location, reserve, callnumber.
*/
protected function getItemStatusesForBiblio($id, $patron = null)
{
$result = $this->makeRequest(
{
// Set up the request
$apiUrl = $this->config['Catalog']['host'] . '/';
// Handle the simple case of just a path in $request
if (is_string($request) || !isset($request['path'])) {
$request = [
'path' => $request
];
}
if (is_array($request['path'])) {
$apiUrl .= implode('/', array_map('urlencode', $request['path']));
} else {
$apiUrl .= $request['path'];
}
$client = $this->createHttpClient($apiUrl);
$client->getRequest()->getHeaders()
->addHeaderLine('Authorization', $this->getOAuth2Token());
// Add params
if (!empty($request['query'])) {
$client->setParameterGet($request['query']);
}
if (!empty($request['form'])) {
$client->setParameterPost($request['form']);
} elseif (!empty($request['json'])) {
$client->getRequest()->setContent(json_encode($request['json']));
$client->getRequest()->getHeaders()->addHeaderLine(
'Content-Type',
'application/json'
);
}
if (!empty($request['headers'])) {
$requestHeaders = $client->getRequest()->getHeaders();
foreach ($request['headers'] as $name => $value) {
$requestHeaders->addHeaderLine($name, [$value]);
}
}
/**
* Get Item Statuses
*
* This is responsible for retrieving the status information of a certain
* record.
*
* @param string $id The record id to retrieve the holdings for
* @param array $patron Patron information, if available
*
* @return array An associative array with the following keys:
* id, availability (boolean), status, location, reserve, callnumber.
*/
protected function getItemStatusesForBiblio($id, $patron = null)
{
$result = $this->makeRequest(
[
'path' => [
'v1', 'contrib', 'kohasuomi', 'availability', 'biblios', $id,
'search'
],
'errors' => true
]
);
if (404 == $result['code']) {
return [];
}
/**if (200 != $result['code']) {
throw new ILSException('Problem with Koha REST API.');
}**/
if (empty($result['data']['item_availabilities'])) {
return [];
}
$statuses = [];
foreach ($result['data']['item_availabilities'] as $i => $item) {
$avail = $item['availability'];
$available = $avail['available'];
/**
* Get Holding
*
* This is responsible for retrieving the holding information of a certain
* record.
*
* @param string $id The record id to retrieve the holdings for
* @param array $patron Patron data
* @param array $options Extra options
*
* @throws ILSException
* @return array On success, an associative array with the following
* keys: id, availability (boolean), status, location, reserve, callnumber,
* duedate, number, barcode.
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function getHolding($id, array $patron = null, array $options = [])
{
return $this->getItemStatusesForBiblio($id, $patron);
}
/**
* Get Purchase History
*
* This is responsible for retrieving the acquisitions history data for the
* specific record (usually recently received issues of a serial).
*
* @param string $id The record id to retrieve the info for
*
* @return mixed An array with the acquisitions data on success.
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function getPurchaseHistory($id)
{
return [];
}
/**
return $holdings;
}
/**
* Default method -- pass along calls to the driver if available; return
* false otherwise. This allows custom functions to be implemented in
* the driver without constant modification to the connection class.
*
* @param string $methodName The name of the called method.
* @param array $params Array of passed parameters.
*
* @throws ILSException
* @return mixed Varies by method (false if undefined method)
*/
public function __call($methodName, $params)
{
try {
if ($this->checkCapability($methodName, $params)) {
return call_user_func_array(
[$this->getDriver(), $methodName],
$params
);
}
} catch (\Exception $e) {
if ($this->failOverToNoILS($e)) {
return call_user_func_array([$this, __METHOD__], func_get_args());
}
throw $e;
}
throw new ILSException(
'Cannot call method: ' . $this->getDriverClass() . '::' . $methodName
);
}
}
return $holdings;
}
/**
* Default method -- pass along calls to the driver if available; return
* false otherwise. This allows custom functions to be implemented in
* the driver without constant modification to the connection class.
*
* @param string $methodName The name of the called method.
* @param array $params Array of passed parameters.
*
* @throws ILSException
* @return mixed Varies by method (false if undefined method)
*/
public function __call($methodName, $params)
{
try {
if ($this->checkCapability($methodName, $params)) {
return call_user_func_array(
[$this->getDriver(), $methodName],
$params
);
}
} catch (\Exception $e) {
if ($this->failOverToNoILS($e)) {
return call_user_func_array([$this, __METHOD__], func_get_args());
}
throw $e;
}
throw new ILSException(
'Cannot call method: ' . $this->getDriverClass() . '::' . $methodName
);
}
}
$params = compact('id', 'patron');
$config = $this->checkCapability('getConfig', ['Holdings', $params])
? $this->getDriver()->getConfig('Holdings', $params) : [];
if (empty($config['itemLimit'])) {
// Use itemLimit in Holds as fallback for backward compatibility:
$config
= $this->checkCapability('getConfig', ['Holds', $params])
? $this->getDriver()->getConfig('Holds', $params) : [];
}
$itemLimit = !empty($config['itemLimit']) ? $config['itemLimit'] : null;
$page = $this->request ? $this->request->getQuery('page', 1) : 1;
$offset = ($itemLimit && is_numeric($itemLimit))
? ($page * $itemLimit) - $itemLimit
: null;
$defaultOptions = compact('page', 'itemLimit', 'offset');
$finalOptions = $options + $defaultOptions;
// Get the holdings from the ILS
$holdings = $this->__call('getHolding', [$id, $patron, $finalOptions]);
// Return all the necessary details:
if (!isset($holdings['holdings'])) {
$holdings = [
'total' => count($holdings),
'holdings' => $holdings,
'electronic_holdings' => [],
];
} else {
if (!isset($holdings['total'])) {
$holdings['total'] = count($holdings['holdings']);
}
if (!isset($holdings['electronic_holdings'])) {
$holdings['electronic_holdings'] = [];
}
}
$holdings['page'] = $finalOptions['page'];
$holdings['itemLimit'] = $finalOptions['itemLimit'];
return $holdings;
}
// Does this ILS Driver handle consortial holdings?
$config = $this->catalog->checkFunction(
'Holds',
compact('id', 'patron')
);
} catch (ILSException $e) {
$patron = false;
$config = [];
}
if (isset($config['consortium']) && $config['consortium'] == true) {
$result = $this->catalog->getConsortialHoldings(
$id,
$patron ? $patron : null,
$ids
);
} else {
$result = $this->catalog
->getHolding($id, $patron ? $patron : null, $options);
}
$grb = 'getRequestBlocks'; // use variable to shorten line below:
$blocks
= $patron && $this->catalog->checkCapability($grb, compact('patron'))
? $this->catalog->getRequestBlocks($patron) : false;
$mode = $this->catalog->getHoldsMode();
if ($mode == "disabled") {
$holdings = $this->standardHoldings($result);
} elseif ($mode == "driver") {
$holdings = $this->driverHoldings($result, $config, !empty($blocks));
} else {
$holdings = $this->generateHoldings($result, $mode, $config);
}
$holdings = $this->processStorageRetrievalRequests(
$holdings,
$id,
*
* @return bool
*/
protected function hasILS()
{
return null !== $this->ils
&& in_array($this->getSourceIdentifier(), $this->ilsBackends);
}
/**
* Get an array of information about record holdings, obtained in real-time
* from the ILS.
*
* @return array
*/
public function getRealTimeHoldings()
{
return $this->hasILS() ? $this->holdLogic->getHoldings(
$this->getUniqueID(),
$this->tryMethod('getConsortialIDs')
) : [];
}
/**
* Get an array of information about record history, obtained in real-time
* from the ILS.
*
* @return array
*/
public function getRealTimeHistory()
{
// Get Acquisitions Data
if (!$this->hasILS()) {
return [];
}
try {
return $this->ils->getPurchaseHistory($this->getUniqueID());
} catch (ILSException $e) {
return [];
}
<?php
// Set up convenience variables:
$account = $this->auth()->getManager();
$user = $account->isLoggedIn();
$openUrl = $this->openUrl($this->driver, 'holdings');
$openUrlActive = $openUrl->isActive();
$doi = $this->doi($this->driver, 'holdings');
$doiActive = $doi->isActive();
// Account for replace_other_urls setting
$urls = $this->record($this->driver)->getLinkDetails($openUrlActive);
$offlineMode = $this->ils()->getOfflineMode();
try {
$holdings = $this->driver->getRealTimeHoldings();
} catch (\VuFind\Exception\ILS $e) {
$holdings = [
'holdings' => [],
'electronic_holdings' => [],
'total' => 0,
'page' => 0,
'itemLimit' => 0
];
$offlineMode = 'ils-offline';
}
// Set page title.
$this->headTitle($this->translate('Holdings') . ': ' . $this->driver->getBreadcrumb());
?>
<?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', ['user' => $this->auth()->isLoggedIn()]); ?>
<?php if (!empty($holdings['blocks'])):?>
<div id="account-block-msg" class="alert alert-danger">
<?=$this->transEsc('account_block_options_missing', ['%%details%%' => implode('; ', $holdings['blocks'])]) ?>
</div>
<?php endif; ?>
<?=($offlineMode == "ils-offline") ? $this->render('Helpers/ils-offline.phtml', ['offlineModeMsg' => 'ils_offline_holdings_message']) : ''?>
<?php if (($this->ils()->getHoldsMode() == 'driver' && !empty($holdings['holdings'])) || $this->ils()->getTitleHoldsMode() == 'driver'): ?>
<?php if ($account->loginEnabled() && $offlineMode != 'ils-offline'): ?>
<?php if (!$user): ?>
$__vars = $this->vars()->getArrayCopy();
if (array_key_exists('this', $__vars)) {
unset($__vars['this']);
}
extract($__vars);
unset($__vars); // remove $__vars from local scope
$this->__content = '';
while ($this->__template = array_pop($this->__templates)) {
$this->__file = $this->resolver($this->__template);
if (! $this->__file) {
throw new Exception\RuntimeException(sprintf(
'%s: Unable to render template "%s"; resolver could not resolve to a file',
__METHOD__,
$this->__template
));
}
try {
ob_start();
$includeReturn = include $this->__file;
$this->__content = ob_get_clean();
} catch (\Throwable $ex) {
ob_end_clean();
throw $ex;
} catch (\Exception $ex) { // @TODO clean up once PHP 7 requirement is enforced
ob_end_clean();
throw $ex;
}
if ($includeReturn === false && empty($this->__content)) {
throw new Exception\UnexpectedValueException(sprintf(
'%s: Unable to render template "%s"; file include failed',
__METHOD__,
$this->__file
));
}
}
$this->setVars(array_pop($this->__varsCache));
if ($this->__filterChain instanceof FilterChain) {
);
$link .= $this->getView()->plugin('searchTabs')
->getCurrentHiddenFilterParams($this->driver->getSourceIdentifier());
return $link;
}
/**
* Render the contents of the specified record tab.
*
* @param \VuFind\RecordTab\TabInterface $tab Tab to display
*
* @return string
*/
public function getTab(\VuFind\RecordTab\TabInterface $tab)
{
$context = ['driver' => $this->driver, 'tab' => $tab];
$classParts = explode('\\', get_class($tab));
$template = 'RecordTab/' . strtolower(array_pop($classParts)) . '.phtml';
$oldContext = $this->contextHelper->apply($context);
$html = $this->view->render($template);
$this->contextHelper->restore($oldContext);
return $html;
}
/**
* Render a toolbar for use on the record view.
*
* @return string
*/
public function getToolbar()
{
return $this->renderTemplate('toolbar.phtml');
}
/**
* Render a search result for the specified view mode.
*
* @param string $view View mode to use.
*
* @return string
$tabClasses[] = 'active';
}
$tabClasses[] = 'initiallyActive';
$activeTabObj = $obj;
}
if (!$obj->isVisible()) { $tabClasses[] = 'hidden'; }
if (!$obj->supportsAjax()) { $tabClasses[] = 'noajax'; }
?>
<li class="<?=implode(' ', $tabClasses)?>" data-tab="<?=$this->escapeHtmlAttr($tabName)?>"<?php if ($obj->supportsAjax() && in_array($tab, $this->backgroundTabs)):?> data-background<?php endif ?>>
<a href="<?=$this->escapeHtmlAttr($this->recordLinker()->getTabUrl($this->driver, $tab))?>#tabnav" data-lightbox-ignore>
<?=$this->transEsc($desc)?>
</a>
</li>
<?php endforeach; ?>
</ul>
<div class="tab-content">
<?php if (!$this->loadInitialTabWithAjax || !isset($activeTabObj) || !$activeTabObj->supportsAjax()): ?>
<div class="tab-pane active <?=$this->escapeHtmlAttr($this->activeTab) ?>-tab">
<?=isset($activeTabObj) ? $this->record($this->driver)->getTab($activeTabObj) : '' ?>
</div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<?=$this->driver->supportsCoinsOpenURL()?'<span class="Z3988" title="' . $this->escapeHtmlAttr($this->driver->getCoinsOpenURL()) . '"></span>':''?>
</div>
<div class="<?=$this->layoutClass('sidebar')?>">
<?php foreach ($sidebarList as $current): ?>
<?=$this->related()->render($current)?>
<?php endforeach; ?>
</div>
</div>
<?=$this->inlineScript(\Laminas\View\Helper\HeadScript::SCRIPT, '$(document).ready(recordDocReady);', 'SET'); ?>
$__vars = $this->vars()->getArrayCopy();
if (array_key_exists('this', $__vars)) {
unset($__vars['this']);
}
extract($__vars);
unset($__vars); // remove $__vars from local scope
$this->__content = '';
while ($this->__template = array_pop($this->__templates)) {
$this->__file = $this->resolver($this->__template);
if (! $this->__file) {
throw new Exception\RuntimeException(sprintf(
'%s: Unable to render template "%s"; resolver could not resolve to a file',
__METHOD__,
$this->__template
));
}
try {
ob_start();
$includeReturn = include $this->__file;
$this->__content = ob_get_clean();
} catch (\Throwable $ex) {
ob_end_clean();
throw $ex;
} catch (\Exception $ex) { // @TODO clean up once PHP 7 requirement is enforced
ob_end_clean();
throw $ex;
}
if ($includeReturn === false && empty($this->__content)) {
throw new Exception\UnexpectedValueException(sprintf(
'%s: Unable to render template "%s"; file include failed',
__METHOD__,
$this->__file
));
}
}
$this->setVars(array_pop($this->__varsCache));
if ($this->__filterChain instanceof FilterChain) {
// If EVENT_RENDERER or EVENT_RENDERER_POST changed the model, make sure
// we use this new model instead of the current $model
$model = $event->getModel();
// If we have children, render them first, but only if:
// a) the renderer does not implement TreeRendererInterface, or
// b) it does, but canRenderTrees() returns false
if ($model->hasChildren()
&& (! $renderer instanceof TreeRendererInterface
|| ! $renderer->canRenderTrees())
) {
$this->renderChildren($model);
}
// Reset the model, in case it has changed, and set the renderer
$event->setModel($model);
$event->setRenderer($renderer);
$rendered = $renderer->render($model);
// If this is a child model, return the rendered content; do not
// invoke the response strategy.
$options = $model->getOptions();
if (array_key_exists('has_parent', $options) && $options['has_parent']) {
return $rendered;
}
$event->setResult($rendered);
$event->setName(ViewEvent::EVENT_RESPONSE);
$events->triggerEvent($event);
}
/**
* Loop through children, rendering each
*
* @param Model $model
* @throws Exception\DomainException
* @return void
$event->setName(ViewEvent::EVENT_RESPONSE);
$events->triggerEvent($event);
}
/**
* Loop through children, rendering each
*
* @param Model $model
* @throws Exception\DomainException
* @return void
*/
protected function renderChildren(Model $model)
{
foreach ($model as $child) {
if ($child->terminate()) {
throw new Exception\DomainException('Inconsistent state; child view model is marked as terminal');
}
$child->setOption('has_parent', true);
$result = $this->render($child);
$child->setOption('has_parent', null);
$capture = $child->captureTo();
if (! empty($capture)) {
if ($child->isAppend()) {
$oldResult = $model->{$capture};
$model->setVariable($capture, $oldResult . $result);
} else {
$model->setVariable($capture, $result);
}
}
}
}
/**
* Create and return ViewEvent used by render()
*
* @return ViewEvent
*/
protected function getEvent()
{
__METHOD__
));
}
$event->setRenderer($renderer);
$event->setName(ViewEvent::EVENT_RENDERER_POST);
$events->triggerEvent($event);
// If EVENT_RENDERER or EVENT_RENDERER_POST changed the model, make sure
// we use this new model instead of the current $model
$model = $event->getModel();
// If we have children, render them first, but only if:
// a) the renderer does not implement TreeRendererInterface, or
// b) it does, but canRenderTrees() returns false
if ($model->hasChildren()
&& (! $renderer instanceof TreeRendererInterface
|| ! $renderer->canRenderTrees())
) {
$this->renderChildren($model);
}
// Reset the model, in case it has changed, and set the renderer
$event->setModel($model);
$event->setRenderer($renderer);
$rendered = $renderer->render($model);
// If this is a child model, return the rendered content; do not
// invoke the response strategy.
$options = $model->getOptions();
if (array_key_exists('has_parent', $options) && $options['has_parent']) {
return $rendered;
}
$event->setResult($rendered);
$event->setName(ViewEvent::EVENT_RESPONSE);
$events->triggerEvent($event);
}
if ($result instanceof Response) {
return $result;
}
// Martial arguments
$request = $e->getRequest();
$response = $e->getResponse();
$viewModel = $e->getViewModel();
if (! $viewModel instanceof ViewModel) {
return;
}
$view = $this->view;
$view->setRequest($request);
$view->setResponse($response);
$caughtException = null;
try {
$view->render($viewModel);
} catch (\Throwable $ex) {
$caughtException = $ex;
} catch (\Exception $ex) { // @TODO clean up once PHP 7 requirement is enforced
$caughtException = $ex;
}
if ($caughtException !== null) {
if ($e->getName() === MvcEvent::EVENT_RENDER_ERROR) {
throw $caughtException;
}
$application = $e->getApplication();
$events = $application->getEventManager();
$e->setError(Application::ERROR_EXCEPTION);
$e->setParam('exception', $caughtException);
$e->setName(MvcEvent::EVENT_RENDER_ERROR);
$events->triggerEvent($e);
}
}
if ($this->sharedManager) {
foreach ($this->sharedManager->getListeners($this->identifiers, $name) as $priority => $listeners) {
$listOfListenersByPriority[$priority][] = $listeners;
}
}
// Sort by priority in reverse order
krsort($listOfListenersByPriority);
// Initial value of stop propagation flag should be false
$event->stopPropagation(false);
// Execute listeners
$responses = new ResponseCollection();
foreach ($listOfListenersByPriority as $listOfListeners) {
foreach ($listOfListeners as $listeners) {
foreach ($listeners as $listener) {
$response = $listener($event);
$responses->push($response);
// If the event was asked to stop propagating, do so
if ($event->propagationIsStopped()) {
$responses->setStopped(true);
return $responses;
}
// If the result causes our validation callback to return true,
// stop propagation
if ($callback && $callback($response)) {
$responses->setStopped(true);
return $responses;
}
}
}
}
return $responses;
}
$event = clone $this->eventPrototype;
$event->setName($eventName);
if ($target !== null) {
$event->setTarget($target);
}
if ($argv) {
$event->setParams($argv);
}
return $this->triggerListeners($event, $callback);
}
/**
* @inheritDoc
*/
public function triggerEvent(EventInterface $event)
{
return $this->triggerListeners($event);
}
/**
* @inheritDoc
*/
public function triggerEventUntil(callable $callback, EventInterface $event)
{
return $this->triggerListeners($event, $callback);
}
/**
* @inheritDoc
*/
public function attach($eventName, callable $listener, $priority = 1)
{
if (! is_string($eventName)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a string for the event; received %s',
__METHOD__,
(is_object($eventName) ? get_class($eventName) : gettype($eventName))
return $this->completeRequest($event);
}
/**
* Complete the request
*
* Triggers "render" and "finish" events, and returns response from
* event object.
*
* @param MvcEvent $event
* @return Application
*/
protected function completeRequest(MvcEvent $event)
{
$events = $this->events;
$event->setTarget($this);
$event->setName(MvcEvent::EVENT_RENDER);
$event->stopPropagation(false); // Clear before triggering
$events->triggerEvent($event);
$event->setName(MvcEvent::EVENT_FINISH);
$event->stopPropagation(false); // Clear before triggering
$events->triggerEvent($event);
return $this;
}
}
// Trigger dispatch event
$event->setName(MvcEvent::EVENT_DISPATCH);
$event->stopPropagation(false); // Clear before triggering
$result = $events->triggerEventUntil($shortCircuit, $event);
// Complete response
$response = $result->last();
if ($response instanceof ResponseInterface) {
$event->setName(MvcEvent::EVENT_FINISH);
$event->setTarget($this);
$event->setResponse($response);
$event->stopPropagation(false); // Clear before triggering
$events->triggerEvent($event);
$this->response = $response;
return $this;
}
$response = $this->response;
$event->setResponse($response);
return $this->completeRequest($event);
}
/**
* Complete the request
*
* Triggers "render" and "finish" events, and returns response from
* event object.
*
* @param MvcEvent $event
* @return Application
*/
protected function completeRequest(MvcEvent $event)
{
$events = $this->events;
$event->setTarget($this);
$event->setName(MvcEvent::EVENT_RENDER);
$event->stopPropagation(false); // Clear before triggering
$events->triggerEvent($event);
$pathParts[] = APPLICATION_PATH . '/vendor';
$pathParts[] = get_include_path();
set_include_path(implode(PATH_SEPARATOR, $pathParts));
// Composer autoloading
if (file_exists('vendor/autoload.php')) {
$loader = include 'vendor/autoload.php';
}
if (!class_exists('Laminas\Loader\AutoloaderFactory')) {
throw new RuntimeException('Unable to load Laminas autoloader.');
}
// Run the application!
$app = Laminas\Mvc\Application::init(require 'config/application.config.php');
if (PHP_SAPI === 'cli') {
return $app->getServiceManager()
->get(\VuFindConsole\ConsoleRunner::class)->run();
} else {
$app->run();
}