*
* @return object
* @throws ServiceNotFoundException If unable to resolve the service.
* @throws ServiceNotCreatedException If an exception is raised when creating a service.
* @throws ContainerExceptionInterface If any other error occurs.
*/
private function doCreate(string $resolvedName, ?array $options = null)
{
try {
if (! isset($this->delegators[$resolvedName])) {
// Let's create the service by fetching the factory
$factory = $this->getFactory($resolvedName);
$object = $factory($this->creationContext, $resolvedName, $options);
} else {
$object = $this->createDelegatorFromName($resolvedName, $options);
}
} catch (ContainerExceptionInterface $exception) {
throw $exception;
} catch (Exception $exception) {
throw new ServiceNotCreatedException(sprintf(
'Service with name "%s" could not be created. Reason: %s',
$resolvedName,
$exception->getMessage()
), (int) $exception->getCode(), $exception);
}
foreach ($this->initializers as $initializer) {
$initializer($this->creationContext, $object);
}
return $object;
}
/**
* Create the lazy services delegator factory.
*
* Creates the lazy services delegator factory based on the lazy_services
* configuration present.
*
* @throws ServiceNotCreatedException When the lazy service class_map configuration is missing.
Arguments
"Service with name "VuFind\Crypt\HMAC" could not be created. Reason: Attempt to read property "HMACkey" on null"
* @param null|array $options Extra options (optional)
*
* @return object
*
* @throws ServiceNotFoundException if unable to resolve the service.
* @throws ServiceNotCreatedException if an exception is raised when
* creating a service.
* @throws ContainerException&\Throwable if any other error occurs
*/
public function __invoke(
ContainerInterface $container,
$requestedName,
array $options = null
) {
if (!empty($options)) {
throw new \Exception('Unexpected options sent to factory.');
}
$config = $container->get(\VuFind\Config\PluginManager::class)
->get('config');
return new $requestedName($config->Security->HMACkey);
}
}
Arguments
"Attempt to read property "HMACkey" on null"
* @param null|array $options Extra options (optional)
*
* @return object
*
* @throws ServiceNotFoundException if unable to resolve the service.
* @throws ServiceNotCreatedException if an exception is raised when
* creating a service.
* @throws ContainerException&\Throwable if any other error occurs
*/
public function __invoke(
ContainerInterface $container,
$requestedName,
array $options = null
) {
if (!empty($options)) {
throw new \Exception('Unexpected options sent to factory.');
}
$config = $container->get(\VuFind\Config\PluginManager::class)
->get('config');
return new $requestedName($config->Security->HMACkey);
}
}
return $creationCallback();
}
/**
* Create a new instance with an already resolved name
*
* This is a highly performance sensitive method, do not modify if you have not benchmarked it carefully
*
* @return object
* @throws ServiceNotFoundException If unable to resolve the service.
* @throws ServiceNotCreatedException If an exception is raised when creating a service.
* @throws ContainerExceptionInterface If any other error occurs.
*/
private function doCreate(string $resolvedName, ?array $options = null)
{
try {
if (! isset($this->delegators[$resolvedName])) {
// Let's create the service by fetching the factory
$factory = $this->getFactory($resolvedName);
$object = $factory($this->creationContext, $resolvedName, $options);
} else {
$object = $this->createDelegatorFromName($resolvedName, $options);
}
} catch (ContainerExceptionInterface $exception) {
throw $exception;
} catch (Exception $exception) {
throw new ServiceNotCreatedException(sprintf(
'Service with name "%s" could not be created. Reason: %s',
$resolvedName,
$exception->getMessage()
), (int) $exception->getCode(), $exception);
}
foreach ($this->initializers as $initializer) {
$initializer($this->creationContext, $object);
}
return $object;
}
// We now deal with requests which may be aliases.
$resolvedName = $this->aliases[$name] ?? $name;
// Update shared service information as we checked if the alias was shared before.
if ($resolvedName !== $name) {
$sharedService = $this->shared[$resolvedName] ?? $sharedService;
}
// The following is only true if the requested service is a shared alias.
$sharedAlias = $sharedService && isset($this->services[$resolvedName]);
// If the alias is configured as a shared service, we are done.
if ($sharedAlias) {
$this->services[$name] = $this->services[$resolvedName];
return $this->services[$resolvedName];
}
// At this point, we have to create the object.
// We use the resolved name for that.
$object = $this->doCreate($resolvedName);
// Cache the object for later, if it is supposed to be shared.
if ($sharedService) {
$this->services[$resolvedName] = $object;
}
// Also cache under the alias name; this allows sharing based on the
// service name used.
if ($sharedAlias) {
$this->services[$name] = $object;
}
return $object;
}
/** {@inheritDoc} */
public function build($name, ?array $options = null)
{
// We never cache when using "build".
$name = $this->aliases[$name] ?? $name;
*
* @return object
*
* @throws ServiceNotFoundException if unable to resolve the service.
* @throws ServiceNotCreatedException if an exception is raised when
* creating a service.
* @throws ContainerException&\Throwable if any other error occurs
*/
public function __invoke(
ContainerInterface $container,
$requestedName,
array $options = null
) {
if (!empty($options)) {
throw new \Exception('Unexpected options sent to factory.');
}
return new $requestedName(
$container->get(\VuFind\Auth\ILSAuthenticator::class),
$container->get(\VuFind\ILS\Connection::class),
$container->get(\VuFind\Crypt\HMAC::class),
$container->get(\VuFind\Config\PluginManager::class)->get('config')
);
}
}
return $creationCallback();
}
/**
* Create a new instance with an already resolved name
*
* This is a highly performance sensitive method, do not modify if you have not benchmarked it carefully
*
* @return object
* @throws ServiceNotFoundException If unable to resolve the service.
* @throws ServiceNotCreatedException If an exception is raised when creating a service.
* @throws ContainerExceptionInterface If any other error occurs.
*/
private function doCreate(string $resolvedName, ?array $options = null)
{
try {
if (! isset($this->delegators[$resolvedName])) {
// Let's create the service by fetching the factory
$factory = $this->getFactory($resolvedName);
$object = $factory($this->creationContext, $resolvedName, $options);
} else {
$object = $this->createDelegatorFromName($resolvedName, $options);
}
} catch (ContainerExceptionInterface $exception) {
throw $exception;
} catch (Exception $exception) {
throw new ServiceNotCreatedException(sprintf(
'Service with name "%s" could not be created. Reason: %s',
$resolvedName,
$exception->getMessage()
), (int) $exception->getCode(), $exception);
}
foreach ($this->initializers as $initializer) {
$initializer($this->creationContext, $object);
}
return $object;
}
// We now deal with requests which may be aliases.
$resolvedName = $this->aliases[$name] ?? $name;
// Update shared service information as we checked if the alias was shared before.
if ($resolvedName !== $name) {
$sharedService = $this->shared[$resolvedName] ?? $sharedService;
}
// The following is only true if the requested service is a shared alias.
$sharedAlias = $sharedService && isset($this->services[$resolvedName]);
// If the alias is configured as a shared service, we are done.
if ($sharedAlias) {
$this->services[$name] = $this->services[$resolvedName];
return $this->services[$resolvedName];
}
// At this point, we have to create the object.
// We use the resolved name for that.
$object = $this->doCreate($resolvedName);
// Cache the object for later, if it is supposed to be shared.
if ($sharedService) {
$this->services[$resolvedName] = $object;
}
// Also cache under the alias name; this allows sharing based on the
// service name used.
if ($sharedAlias) {
$this->services[$name] = $object;
}
return $object;
}
/** {@inheritDoc} */
public function build($name, ?array $options = null)
{
// We never cache when using "build".
$name = $this->aliases[$name] ?? $name;
* @param array|null $options Service options
*
* @return AbstractBase
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function __invoke(
ContainerInterface $container,
$name,
callable $callback,
array $options = null
) {
$driver = call_user_func($callback);
// Attach the ILS if at least one backend supports it:
$ilsBackends = $this->getIlsBackends($container);
if (!empty($ilsBackends) && $container->has(\VuFind\ILS\Connection::class)) {
$driver->attachILS(
$container->get(\VuFind\ILS\Connection::class),
$container->get(\VuFind\ILS\Logic\Holds::class),
$container->get(\VuFind\ILS\Logic\TitleHolds::class)
);
$driver->setIlsBackends($ilsBackends);
}
return $driver;
}
/**
* Get the ILS backend configuration.
*
* @param ContainerInterface $container Service container
*
* @return string[]
*/
protected function getIlsBackends(ContainerInterface $container)
{
// Get a list of ILS-compatible backends.
static $ilsBackends = null;
if (!is_array($ilsBackends)) {
};
$initialCreationContext = $this->creationContext;
foreach ($this->delegators[$name] as $index => $delegatorFactory) {
$delegatorFactory = $this->delegators[$name][$index];
if ($delegatorFactory === LazyServiceFactory::class) {
$delegatorFactory = $this->createLazyServiceDelegatorFactory();
} elseif (is_string($delegatorFactory) && class_exists($delegatorFactory)) {
$delegatorFactory = new $delegatorFactory();
}
$this->assertCallableDelegatorFactory($delegatorFactory);
$this->delegators[$name][$index] = $delegatorFactory;
$creationCallback =
/** @return object */
static fn() => $delegatorFactory($initialCreationContext, $name, $creationCallback, $options);
}
return $creationCallback();
}
/**
* Create a new instance with an already resolved name
*
* This is a highly performance sensitive method, do not modify if you have not benchmarked it carefully
*
* @return object
* @throws ServiceNotFoundException If unable to resolve the service.
* @throws ServiceNotCreatedException If an exception is raised when creating a service.
* @throws ContainerExceptionInterface If any other error occurs.
*/
private function doCreate(string $resolvedName, ?array $options = null)
{
try {
if (! isset($this->delegators[$resolvedName])) {
// Let's create the service by fetching the factory
foreach ($this->delegators[$name] as $index => $delegatorFactory) {
$delegatorFactory = $this->delegators[$name][$index];
if ($delegatorFactory === LazyServiceFactory::class) {
$delegatorFactory = $this->createLazyServiceDelegatorFactory();
} elseif (is_string($delegatorFactory) && class_exists($delegatorFactory)) {
$delegatorFactory = new $delegatorFactory();
}
$this->assertCallableDelegatorFactory($delegatorFactory);
$this->delegators[$name][$index] = $delegatorFactory;
$creationCallback =
/** @return object */
static fn() => $delegatorFactory($initialCreationContext, $name, $creationCallback, $options);
}
return $creationCallback();
}
/**
* Create a new instance with an already resolved name
*
* This is a highly performance sensitive method, do not modify if you have not benchmarked it carefully
*
* @return object
* @throws ServiceNotFoundException If unable to resolve the service.
* @throws ServiceNotCreatedException If an exception is raised when creating a service.
* @throws ContainerExceptionInterface If any other error occurs.
*/
private function doCreate(string $resolvedName, ?array $options = null)
{
try {
if (! isset($this->delegators[$resolvedName])) {
// Let's create the service by fetching the factory
$factory = $this->getFactory($resolvedName);
$object = $factory($this->creationContext, $resolvedName, $options);
} else {
/**
* Create a new instance with an already resolved name
*
* This is a highly performance sensitive method, do not modify if you have not benchmarked it carefully
*
* @return object
* @throws ServiceNotFoundException If unable to resolve the service.
* @throws ServiceNotCreatedException If an exception is raised when creating a service.
* @throws ContainerExceptionInterface If any other error occurs.
*/
private function doCreate(string $resolvedName, ?array $options = null)
{
try {
if (! isset($this->delegators[$resolvedName])) {
// Let's create the service by fetching the factory
$factory = $this->getFactory($resolvedName);
$object = $factory($this->creationContext, $resolvedName, $options);
} else {
$object = $this->createDelegatorFromName($resolvedName, $options);
}
} catch (ContainerExceptionInterface $exception) {
throw $exception;
} catch (Exception $exception) {
throw new ServiceNotCreatedException(sprintf(
'Service with name "%s" could not be created. Reason: %s',
$resolvedName,
$exception->getMessage()
), (int) $exception->getCode(), $exception);
}
foreach ($this->initializers as $initializer) {
$initializer($this->creationContext, $object);
}
return $object;
}
/**
* Create the lazy services delegator factory.
// We now deal with requests which may be aliases.
$resolvedName = $this->aliases[$name] ?? $name;
// Update shared service information as we checked if the alias was shared before.
if ($resolvedName !== $name) {
$sharedService = $this->shared[$resolvedName] ?? $sharedService;
}
// The following is only true if the requested service is a shared alias.
$sharedAlias = $sharedService && isset($this->services[$resolvedName]);
// If the alias is configured as a shared service, we are done.
if ($sharedAlias) {
$this->services[$name] = $this->services[$resolvedName];
return $this->services[$resolvedName];
}
// At this point, we have to create the object.
// We use the resolved name for that.
$object = $this->doCreate($resolvedName);
// Cache the object for later, if it is supposed to be shared.
if ($sharedService) {
$this->services[$resolvedName] = $object;
}
// Also cache under the alias name; this allows sharing based on the
// service name used.
if ($sharedAlias) {
$this->services[$name] = $object;
}
return $object;
}
/** {@inheritDoc} */
public function build($name, ?array $options = null)
{
// We never cache when using "build".
$name = $this->aliases[$name] ?? $name;
* a service definition for the instance, and the service is not
* auto-invokable.
* @throws InvalidServiceException If the plugin created is invalid for the
* plugin context.
*/
public function get($name, ?array $options = null)
{
if (! $this->has($name)) {
if (! $this->autoAddInvokableClass || ! class_exists($name)) {
throw new Exception\ServiceNotFoundException(sprintf(
'A plugin by the name "%s" was not found in the plugin manager %s',
$name,
static::class
));
}
$this->setFactory($name, Factory\InvokableFactory::class);
}
$instance = ! $options ? parent::get($name) : $this->build($name, $options);
$this->validate($instance);
return $instance;
}
/**
* {@inheritDoc}
*
* @psalm-assert InstanceType $instance
*/
public function validate(mixed $instance)
{
if (method_exists($this, 'validatePlugin')) {
trigger_error(sprintf(
'%s::validatePlugin() has been deprecated as of 3.0; please define validate() instead',
static::class
), E_USER_DEPRECATED);
$this->validatePlugin($instance);
return;
}
*
* @category VuFind
* @package ServiceManager
* @author Demian Katz <demian.katz@villanova.edu>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development Wiki
*/
trait LowerCaseServiceNameTrait
{
/**
* Retrieve a plugin
*
* @param string $name Name of plugin
* @param null|array $options Options to use when creating the instance.
*
* @return mixed
*/
public function get($name, array $options = null)
{
return parent::get($this->getNormalizedServiceName($name), $options);
}
/**
* Returns true if the container can return an entry for the given identifier.
* Returns false otherwise.
*
* @param string $id Identifier of the entry to look for.
*
* @return bool
*/
public function has($id)
{
return parent::has($this->getNormalizedServiceName($id));
}
/**
* Hack for backward compatibility with services defined under
* ServiceManager v2, when service names were case-insensitive.
* TODO: set up aliases and/or normalize code to eliminate the need for this.
*
* @param string $defaultKeySuffix Default key suffix
*
* @return AbstractBase
*/
public function getSolrRecord(
$data,
$keyPrefix = 'Solr',
$defaultKeySuffix = 'Default'
) {
$key = $keyPrefix . ucwords(
$data['record_format'] ?? $data['recordtype'] ?? $defaultKeySuffix
);
$recordType = $this->has($key) ? $key : $keyPrefix . $defaultKeySuffix;
// Extract highlighting details injected earlier by
// \VuFindSearch\Backend\Solr\Response\Json\RecordCollectionFactory
$hl = $data['__highlight_details'] ?? [];
unset($data['__highlight_details']);
// Build the object:
$driver = $this->get($recordType);
$driver->setRawData($data);
$driver->setHighlightDetails($hl);
return $driver;
}
/**
* Convenience method to retrieve a populated Search2 record driver.
*
* @param array $data Raw Solr data
* @param string $defaultKeySuffix Default key suffix
*
* @return AbstractBase
*/
public function getSearch2Record($data, $defaultKeySuffix = 'Default')
{
return $this->getSolrRecord($data, 'Search2', $defaultKeySuffix);
}
/**
* Convenience method to retrieve a populated Solr authority record driver.
* @return RecordCollection
*/
public function factory($response)
{
if (!is_array($response)) {
throw new InvalidArgumentException(
sprintf(
'Unexpected type of value: Expected array, got %s',
gettype($response)
)
);
}
$collection = new $this->collectionClass($response);
$hlDetails = $response['highlighting'] ?? [];
foreach ($response['response']['docs'] ?? [] as $doc) {
// If highlighting details were provided, merge them into the record for future use:
if (isset($doc['id']) && ($hl = $hlDetails[$doc['id']] ?? [])) {
$doc['__highlight_details'] = $hl;
}
$collection->add(call_user_func($this->recordFactory, $doc), false);
}
return $collection;
}
}
* @return Connector
*/
public function getConnector()
{
return $this->connector;
}
/// Internal API
/**
* Create record collection.
*
* @param string $json Serialized JSON response
*
* @return RecordCollectionInterface
*/
protected function createRecordCollection($json)
{
return $this->getRecordCollectionFactory()
->factory($this->deserialize($json));
}
/**
* Deserialize JSON response.
*
* @param string $json Serialized JSON response
*
* @return array
*
* @throws BackendException Deserialization error
*/
protected function deserialize($json)
{
$response = json_decode($json, true);
$error = json_last_error();
if ($error != \JSON_ERROR_NONE) {
throw new BackendException(
sprintf('JSON decoding error: %s -- %s', $error, $json)
);
}
$params->set('sort', $sort);
return $this->search($query, 0, $limit, $params);
}
/**
* Retrieve a single document.
*
* @param string $id Document identifier
* @param ParamBag $params Search backend parameters
*
* @return RecordCollectionInterface
*/
public function retrieve($id, ParamBag $params = null)
{
$params = $params ?: new ParamBag();
$this->injectResponseWriter($params);
$response = $this->connector->retrieve($id, $params);
$collection = $this->createRecordCollection($response);
$this->injectSourceIdentifier($collection);
return $collection;
}
/**
* Retrieve a batch of documents.
*
* @param array $ids Array of document identifiers
* @param ParamBag $params Search backend parameters
*
* @return RecordCollectionInterface
*/
public function retrieveBatch($ids, ParamBag $params = null)
{
$params = $params ?: new ParamBag();
// Callback function for formatting IDs:
$formatIds = function ($i) {
return '"' . addcslashes($i, '"') . '"';
};
*
* @return CommandInterface Command instance for method chaining
*/
public function execute(BackendInterface $backend): CommandInterface
{
$this->validateBackend($backend);
if (
!($backend instanceof $this->interface)
|| !method_exists($this->interface, $this->method)
) {
throw new BackendException(
"$this->backendId does not support $this->method()"
);
}
$args = $this->getArguments();
if ($backend instanceof ExtraRequestDetailsInterface) {
$backend->resetExtraRequestDetails();
}
$this->finalizeExecution(
call_user_func([$backend, $this->method], ...$args)
);
if ($backend instanceof ExtraRequestDetailsInterface) {
$this->extraRequestDetails = $backend->getExtraRequestDetails();
}
return $this;
}
}
*
* @return CommandInterface Command instance for method chaining
*/
public function execute(BackendInterface $backend): CommandInterface
{
$this->validateBackend($backend);
if (
!($backend instanceof $this->interface)
|| !method_exists($this->interface, $this->method)
) {
throw new BackendException(
"$this->backendId does not support $this->method()"
);
}
$args = $this->getArguments();
if ($backend instanceof ExtraRequestDetailsInterface) {
$backend->resetExtraRequestDetails();
}
$this->finalizeExecution(
call_user_func([$backend, $this->method], ...$args)
);
if ($backend instanceof ExtraRequestDetailsInterface) {
$this->extraRequestDetails = $backend->getExtraRequestDetails();
}
return $this;
}
}
}
/**
* Invoke a command.
*
* @param CommandInterface $command Command
*
* @return CommandInterface
*/
public function invoke(CommandInterface $command)
{
// The backend instance is no longer added as an event parameter.
// All other legacy event parameters are accessible via the command object.
$args = ['command' => $command];
$backend = $this->resolve($command->getTargetIdentifier(), $args);
$this->triggerPre($this, $args);
try {
$command->execute($backend);
} catch (BackendException $e) {
$args['error'] = $e;
$this->triggerError($this, $args);
throw $e;
}
$this->triggerPost($this, $args);
return $command;
}
/**
* Resolve a backend.
*
* @param string $backendId Backend name
* @param array|ArrayAccess $args Service function arguments
*
* @return BackendInterface
*
* @throws Exception\RuntimeException Unable to resolve backend
*/
* @return \VuFind\RecordDriver\AbstractBase
*/
public function load(
$id,
$source = DEFAULT_SEARCH_BACKEND,
$tolerateMissing = false,
ParamBag $params = null
) {
if (null !== $id && '' !== $id) {
$results = [];
if (
null !== $this->recordCache
&& $this->recordCache->isPrimary($source)
) {
$results = $this->recordCache->lookup($id, $source);
}
if (empty($results)) {
try {
$command = new RetrieveCommand($source, $id, $params);
$results = $this->searchService->invoke($command)
->getResult()->getRecords();
} catch (BackendException $e) {
if (!$tolerateMissing) {
throw $e;
}
}
}
if (
empty($results) && null !== $this->recordCache
&& $this->recordCache->isFallback($source)
) {
$results = $this->recordCache->lookup($id, $source);
if (!empty($results)) {
$results[0]->setExtraDetail('cached_record', true);
}
}
if (!empty($results)) {
return $results[0];
}
* @param ParamBag $params Search backend parameters
* @param bool $force Set to true to force a reload of the record, even if
* already loaded (useful if loading a record using different parameters)
*
* @return AbstractRecordDriver
*/
protected function loadRecord(ParamBag $params = null, bool $force = false)
{
// Only load the record if it has not already been loaded. Note that
// when determining record ID, we check both the route match (the most
// common scenario) and the GET parameters (a fallback used by some
// legacy routes).
if ($force || !is_object($this->driver)) {
$recordLoader = $this->getRecordLoader();
$cacheContext = $this->getRequest()->getQuery()->get('cacheContext');
if (isset($cacheContext)) {
$recordLoader->setCacheContext($cacheContext);
}
$this->driver = $recordLoader->load(
$this->params()->fromRoute('id', $this->params()->fromQuery('id')),
$this->sourceId,
false,
$params
);
}
return $this->driver;
}
/**
* Redirect the user to the main record view.
*
* @param string $params Parameters to append to record URL.
* @param string $tab Record tab to display (null for default).
*
* @return mixed
*/
protected function redirectToRecord($params = '', $tab = null)
{
$details = $this->getRecordRouter()
->getTabRouteDetails($this->loadRecord(), $tab);
/**
* Show permanent link for the current record.
*
* @return \Laminas\View\Model\ViewModel
*/
public function permalinkAction()
{
$view = $this->createViewModel();
$view->setTemplate('record/permalink');
return $view;
}
/**
* Export the record
*
* @return mixed
*/
public function exportAction()
{
$driver = $this->loadRecord();
$view = $this->createViewModel();
$format = $this->params()->fromQuery('style');
// Display export menu if missing/invalid option
$export = $this->getService(\VuFind\Export::class);
if (empty($format) || !$export->recordSupportsFormat($driver, $format)) {
if (!empty($format)) {
$this->flashMessenger()
->addMessage('export_invalid_format', 'error');
}
$view->setTemplate('record/export-menu');
return $view;
}
// If this is an export format that redirects to an external site, perform
// the redirect now (unless we're being called back from that service!):
if (
$export->needsRedirect($format)
&& !$this->params()->fromQuery('callback')
) {
*/
public function onDispatch(MvcEvent $e)
{
$routeMatch = $e->getRouteMatch();
if (! $routeMatch) {
/**
* @todo Determine requirements for when route match is missing.
* Potentially allow pulling directly from request metadata?
*/
throw new DomainException('Missing route matches; unsure how to retrieve action');
}
$action = $routeMatch->getParam('action', 'not-found');
$method = static::getMethodFromAction($action);
if (! method_exists($this, $method)) {
$method = 'notFoundAction';
}
$actionResponse = $this->$method();
$e->setResult($actionResponse);
return $actionResponse;
}
}
}
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 (is_callable($callback) && $callback($response)) {
$responses->setStopped(true);
return $responses;
}
}
}
}
return $responses;
}
$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__,
get_debug_type($eventName),
));
}
$this->events[$eventName][(int) $priority][0][] = $listener;
return $listener;
}
/**
* @events dispatch.pre, dispatch.post
* @param Request $request
* @param null|Response $response
* @return Response|mixed
*/
public function dispatch(Request $request, ?Response $response = null)
{
$this->request = $request;
if (! $response) {
$response = new HttpResponse();
}
$this->response = $response;
$e = $this->getEvent();
$e->setName(MvcEvent::EVENT_DISPATCH);
$e->setRequest($request);
$e->setResponse($response);
$e->setTarget($this);
$result = $this->getEventManager()->triggerEventUntil(static fn($test): bool => $test instanceof Response, $e);
if ($result->stopped()) {
return $result->last();
}
return $e->getResult();
}
/**
* Get request object
*
* @return Request
*/
public function getRequest()
{
if (! $this->request) {
$this->request = new HttpRequest();
}
return $this->request;
);
return $this->complete($return, $e);
} catch (Throwable $exception) {
$return = $this->marshalBadControllerEvent($controllerName, $e, $application, $exception);
return $this->complete($return, $e);
} catch (Exception $exception) { // @TODO clean up once PHP 7 requirement is enforced
$return = $this->marshalBadControllerEvent($controllerName, $e, $application, $exception);
return $this->complete($return, $e);
}
if ($controller instanceof InjectApplicationEventInterface) {
$controller->setEvent($e);
}
$request = $e->getRequest();
$response = $application->getResponse();
$caughtException = null;
try {
$return = $controller->dispatch($request, $response);
} catch (Throwable $ex) {
$caughtException = $ex;
} catch (Exception $ex) { // @TODO clean up once PHP 7 requirement is enforced
$caughtException = $ex;
}
if ($caughtException !== null) {
$e->setName(MvcEvent::EVENT_DISPATCH_ERROR);
$e->setError($application::ERROR_EXCEPTION);
$e->setController($controllerName);
$e->setControllerClass($controller::class);
$e->setParam('exception', $caughtException);
$return = $application->getEventManager()->triggerEvent($e)->last();
if (! $return) {
$return = $e->getResult();
}
}
return $this->complete($return, $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 (is_callable($callback) && $callback($response)) {
$responses->setStopped(true);
return $responses;
}
}
}
}
return $responses;
}
$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__,
get_debug_type($eventName),
));
}
$this->events[$eventName][(int) $priority][0][] = $listener;
return $listener;
}
/**
$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;
}
}
if ($event->getError()) {
return $this->completeRequest($event);
}
// 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
$vufindProfiler = getenv('VUFIND_PROFILER_XHPROF');
if (!empty($vufindProfiler)) {
include __DIR__ . '/../module/VuFind/functions/profiler.php';
enableVuFindProfiling($vufindProfiler);
}
// Run the application!
$app = include __DIR__ . '/../config/application.php';
if (PHP_SAPI === 'cli') {
return $app->getServiceManager()
->get(\VuFindConsole\ConsoleRunner::class)->run();
} else {
// Setup remote code coverage if enabled:
if (getenv('VUFIND_CODE_COVERAGE')) {
$modules = $app->getServiceManager()
->get(\Laminas\ModuleManager\ModuleManager::class)->getModules();
include __DIR__ . '/../module/VuFind/functions/codecoverage.php';
setupVuFindRemoteCodeCoverage($modules);
}
$app->run();
}