/usr
/local
/vufind
/module
/VuFindSearch
/src
/VuFindSearch
/Backend
/Exception
/HttpErrorException.php
* @var Response
*/
protected $response;
/**
* Exception factory.
*
* Returns a RequestErrorException or RemoteErrorException depending on
* the response's status code.
*
* @param Response $response Server response
*
* @return RequestErrorException|RemoteErrorException
*/
public static function createFromResponse(Response $response)
{
$status = $response->getStatusCode();
$phrase = $response->getReasonPhrase();
if ($status >= 500) {
return new RemoteErrorException(
$status . ' ' . $phrase, $status, $response
);
} else {
return new RequestErrorException(
$status . ' ' . $phrase, $status, $response
);
}
}
/**
* Constructor.
*
* @param string $message Exception message
* @param int $code Exception code
* @param Response $response Server response
* @param Exception $prev Previous exception
*
* @return void
*/
public function __construct($message, $code, Response $response,
/usr
/local
/vufind
/module
/VuFindSearch
/src
/VuFindSearch
/Backend
/Solr
/Connector.php
*/
protected function send(HttpClient $client)
{
$this->debug(
sprintf('=> %s %s', $client->getMethod(), $client->getUri())
);
$time = microtime(true);
$response = $client->send();
$time = microtime(true) - $time;
$this->debug(
sprintf(
'<= %s %s', $response->getStatusCode(),
$response->getReasonPhrase()
), ['time' => $time]
);
if (!$response->isSuccess()) {
throw HttpErrorException::createFromResponse($response);
}
return $response->getBody();
}
/**
* Create the HTTP client.
*
* @param string $url Target URL
* @param string $method Request method
*
* @return HttpClient
*/
protected function createClient($url, $method)
{
$client = new HttpClient();
$client->setAdapter($this->adapter);
$client->setOptions(['timeout' => $this->timeout]);
$client->setUri($url);
$client->setMethod($method);
if ($this->proxy) {
/usr
/local
/vufind
/module
/VuFindSearch
/src
/VuFindSearch
/Backend
/Solr
/Connector.php
*
* @return string Response body
*
* @throws RemoteErrorException SOLR signaled a server error (HTTP 5xx)
* @throws RequestErrorException SOLR signaled a client error (HTTP 4xx)
*/
protected function trySolrUrls($method, $urlSuffix, $callback = null)
{
// This exception should never get thrown; it's just a safety in case
// something unanticipated occurs.
$exception = new \Exception('Unexpected exception.');
// Loop through all base URLs and try them in turn until one works.
foreach ((array)$this->url as $base) {
$client = $this->createClient($base . $urlSuffix, $method);
if (is_callable($callback)) {
$callback($client);
}
try {
return $this->send($client);
} catch (\Exception $ex) {
if ($this->isRethrowableSolrException($ex)) {
throw $ex;
}
$exception = $ex;
}
}
// If we got this far, everything failed -- throw the most recent
// exception caught above.
throw $exception;
}
/**
* Send request the SOLR and return the response.
*
* @param HttpClient $client Prepared HTTP client
*
* @return string Response body
*
/usr
/local
/vufind
/module
/VuFindSearch
/src
/VuFindSearch
/Backend
/Solr
/Connector.php
*/
public function query($handler, ParamBag $params)
{
$urlSuffix = '/' . $handler;
$paramString = implode('&', $params->request());
if (strlen($paramString) > self::MAX_GET_URL_LENGTH) {
$method = Request::METHOD_POST;
$callback = function ($client) use ($paramString) {
$client->setRawBody($paramString);
$client->setEncType(HttpClient::ENC_URLENCODED);
$client->setHeaders(['Content-Length' => strlen($paramString)]);
};
} else {
$method = Request::METHOD_GET;
$urlSuffix .= '?' . $paramString;
$callback = null;
}
$this->debug(sprintf('Query %s', $paramString));
return $this->trySolrUrls($method, $urlSuffix, $callback);
}
/**
* Check if an exception from a Solr request should be thrown rather than retried
*
* @param \Exception $ex Exception
*
* @return bool
*/
protected function isRethrowableSolrException($ex)
{
return $ex instanceof TimeoutException
|| $ex instanceof RequestErrorException;
}
/**
* Try all Solr URLs until we find one that works (or throw an exception).
*
* @param string $method HTTP method to use
* @param string $urlSuffix Suffix to append to all URLs tried
/usr
/local
/vufind
/module
/VuFindSearch
/src
/VuFindSearch
/Backend
/Solr
/Connector.php
*/
public function similar($id, ParamBag $params)
{
$handler = $this->map->getHandler(__FUNCTION__);
$this->map->prepare(__FUNCTION__, $params);
return $this->query($handler, $params);
}
/**
* Execute a search.
*
* @param ParamBag $params Parameters
*
* @return string
*/
public function search(ParamBag $params)
{
$handler = $this->map->getHandler(__FUNCTION__);
$this->map->prepare(__FUNCTION__, $params);
return $this->query($handler, $params);
}
/**
* Extract terms from a SOLR index.
*
* @param ParamBag $params Parameters
*
* @return string
*/
public function terms(ParamBag $params)
{
$handler = $this->map->getHandler(__FUNCTION__);
$this->map->prepare(__FUNCTION__, $params);
return $this->query($handler, $params);
}
/**
* Write to the SOLR index.
*
/usr
/local
/vufind
/module
/VuFindSearch
/src
/VuFindSearch
/Backend
/Solr
/Backend.php
/**
* Perform a search and return record collection.
*
* @param AbstractQuery $query Search query
* @param int $offset Search offset
* @param int $limit Search limit
* @param ParamBag $params Search backend parameters
*
* @return RecordCollectionInterface
*/
public function search(AbstractQuery $query, $offset, $limit,
ParamBag $params = null
) {
$params = $params ?: new ParamBag();
$this->injectResponseWriter($params);
$params->set('rows', $limit);
$params->set('start', $offset);
$params->mergeWith($this->getQueryBuilder()->build($query));
$response = $this->connector->search($params);
$collection = $this->createRecordCollection($response);
$this->injectSourceIdentifier($collection);
return $collection;
}
/**
* Get Random records
*
* @param AbstractQuery $query Search query
* @param int $limit Search limit
* @param ParamBag $params Search backend parameters
*
* @return RecordCollectionInterface
*/
public function random(
AbstractQuery $query, $limit, ParamBag $params = null
) {
$params = $params ?: new ParamBag();
$this->injectResponseWriter($params);
/usr
/local
/vufind
/module
/VuFindSearch
/src
/VuFindSearch
/Service.php
* @param string $backend Search backend identifier
* @param Query\AbstractQuery $query Search query
* @param int $offset Search offset
* @param int $limit Search limit
* @param ParamBag $params Search backend parameters
*
* @return RecordCollectionInterface
*/
public function search($backend, Query\AbstractQuery $query, $offset = 0,
$limit = 20, ParamBag $params = null
) {
$params = $params ?: new ParamBag();
$context = __FUNCTION__;
$args = compact('backend', 'query', 'offset', 'limit', 'params', 'context');
$backend = $this->resolve($backend, $args);
$args['backend_instance'] = $backend;
$this->triggerPre($backend, $args);
try {
$response = $backend->search($query, $offset, $limit, $params);
} catch (BackendException $e) {
$this->triggerError($e, $args);
throw $e;
}
$this->triggerPost($response, $args);
return $response;
}
/**
* Retrieve a single record.
*
* @param string $backend Search backend identifier
* @param string $id Record identifier
* @param ParamBag $params Search backend parameters
*
* @return RecordCollectionInterface
*/
public function retrieve($backend, $id, ParamBag $params = null)
{
$params = $params ?: new ParamBag();
/usr
/local
/vufind
/module
/VuFind
/src
/VuFind
/Search
/Solr
/Results.php
$this->spellingProcessor = $processor;
}
/**
* Support method for performAndProcessSearch -- perform a search based on the
* parameters passed to the object.
*
* @return void
*/
protected function performSearch()
{
$query = $this->getParams()->getQuery();
$limit = $this->getParams()->getLimit();
$offset = $this->getStartRecord() - 1;
$params = $this->getParams()->getBackendParameters();
$searchService = $this->getSearchService();
try {
$collection = $searchService
->search($this->backendId, $query, $offset, $limit, $params);
} catch (\VuFindSearch\Backend\Exception\BackendException $e) {
// If the query caused a parser error, see if we can clean it up:
if ($e->hasTag('VuFind\Search\ParserError')
&& $newQuery = $this->fixBadQuery($query)
) {
// We need to get a fresh set of $params, since the previous one was
// manipulated by the previous search() call.
$params = $this->getParams()->getBackendParameters();
$collection = $searchService
->search($this->backendId, $newQuery, $offset, $limit, $params);
} else {
throw $e;
}
}
$this->responseFacets = $collection->getFacets();
$this->resultTotal = $collection->getTotal();
// Process spelling suggestions
$spellcheck = $collection->getSpellcheck();
/usr
/local
/vufind
/module
/VuFind
/src
/VuFind
/Search
/Base
/Results.php
{
$this->helpers[$key] = $value;
}
/**
* Actually execute the search.
*
* @return void
*/
public function performAndProcessSearch()
{
// Initialize variables to defaults (to ensure they don't stay null
// and cause unnecessary repeat processing):
$this->resultTotal = 0;
$this->results = [];
$this->suggestions = [];
// Run the search:
$this->startQueryTimer();
$this->performSearch();
$this->stopQueryTimer();
}
/**
* Returns the stored list of facets for the last search
*
* @param array $filter Array of field => on-screen description listing
* all of the desired facet fields; set to null to get all configured values.
*
* @return array Facets data arrays
*/
abstract public function getFacetList($filter = null);
/**
* Abstract support method for performAndProcessSearch -- perform a search based
* on the parameters passed to the object. This method is responsible for
* filling in all of the key class properties: results, resultTotal, etc.
*
* @return void
*/
/usr
/local
/vufind
/module
/VuFind
/src
/VuFind
/Search
/SearchRunner.php
$params = $results->getParams();
$params->setLastView($lastView);
$params->initFromRequest($request);
if (is_callable($setupCallback)) {
$setupCallback($this, $params, $runningSearchId);
}
// Trigger the "configuration done" event.
$this->getEventManager()->trigger(
self::EVENT_CONFIGURED, $this,
compact('params', 'request', 'runningSearchId')
);
// Attempt to perform the search; if there is a problem, inspect any Solr
// exceptions to see if we should communicate to the user about them.
try {
// Explicitly execute search within controller -- this allows us to
// catch exceptions more reliably:
$results->performAndProcessSearch();
} catch (\VuFindSearch\Backend\Exception\BackendException $e) {
if ($e->hasTag('VuFind\Search\ParserError')) {
// We need to create and process an "empty results" object to
// ensure that recommendation modules and templates behave
// properly when displaying the error message.
$results = $this->resultsManager->get('EmptySet');
$results->setParams($params);
$results->performAndProcessSearch();
} else {
throw $e;
}
}
// Trigger the "search completed" event.
$this->getEventManager()->trigger(
self::EVENT_COMPLETE, $this, compact('results', 'runningSearchId')
);
return $results;
}
/usr
/local
/vufind
/module
/VuFind
/src
/VuFind
/Controller
/AbstractSearch.php
{
$view = $this->createViewModel();
// Handle saved search requests:
$savedId = $this->params()->fromQuery('saved', false);
if ($savedId !== false) {
return $this->redirectToSavedSearch($savedId);
}
$runner = $this->serviceLocator->get('VuFind\SearchRunner');
// Send both GET and POST variables to search class:
$request = $this->getRequest()->getQuery()->toArray()
+ $this->getRequest()->getPost()->toArray();
$lastView = $this->getSearchMemory()
->retrieveLastSetting($this->searchClassId, 'view');
$view->results = $results = $runner->run(
$request, $this->searchClassId, $this->getSearchSetupCallback(),
$lastView
);
$view->params = $results->getParams();
// If we received an EmptySet back, that indicates that the real search
// failed due to some kind of syntax error, and we should display a
// warning to the user; otherwise, we should proceed with normal post-search
// processing.
if ($results instanceof \VuFind\Search\EmptySet\Results) {
$view->parseError = true;
} else {
// If a "jumpto" parameter is set, deal with that now:
if ($jump = $this->processJumpTo($results)) {
return $jump;
}
// Remember the current URL as the last search.
$this->rememberSearch($results);
// Add to search history:
if ($this->saveToHistory) {
/usr
/local
/vufind
/module
/VuFind
/src
/VuFind
/Controller
/SearchController.php
*/
public function resultsAction()
{
// Special case -- redirect tag searches.
$tag = $this->params()->fromQuery('tag');
if (!empty($tag)) {
$query = $this->getRequest()->getQuery();
$query->set('lookfor', $tag);
$query->set('type', 'tag');
}
if ($this->params()->fromQuery('type') == 'tag') {
// Because we're coming in from a search, we want to do a fuzzy
// tag search, not an exact search like we would when linking to a
// specific tag name.
$query = $this->getRequest()->getQuery()->set('fuzzy', 'true');
return $this->forwardTo('Tag', 'Home');
}
// Default case -- standard behavior.
return parent::resultsAction();
}
/**
* Get active hidden filter settings.
*
* @return array
*/
protected function getActiveHiddenFilters()
{
return $this->serviceLocator->get('VuFind\SearchTabsHelper')
->getHiddenFilters($this->searchClassId);
}
/**
* Create a results object with hidden filters pre-populated.
*
* @param string $backend ID of results object to create
* @param array $filters Hidden filter settings (null for defaults)
*
* @return \VuFind\Search\Base\Results
/usr
/local
/vufind
/vendor
/zendframework
/zend-mvc
/src
/Controller
/AbstractActionController.php
*/
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 Exception\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;
}
/**
* @deprecated please use the {@see \Zend\Mvc\Controller\Plugin\CreateHttpNotFoundModel} plugin instead: this
* method will be removed in release 2.5 or later.
*
* {@inheritDoc}
*/
protected function createHttpNotFoundModel(HttpResponse $response)
{
return $this->__call('createHttpNotFoundModel', [$response]);
}
/**
* @deprecated please use the {@see \Zend\Mvc\Controller\Plugin\CreateConsoleNotFoundModel} plugin instead: this
* method will be removed in release 2.5 or later.
/usr
/local
/vufind
/vendor
/zendframework
/zend-eventmanager
/src
/EventManager.php
}
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;
}
/usr
/local
/vufind
/vendor
/zendframework
/zend-eventmanager
/src
/EventManager.php
$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))
));
}
$this->events[$eventName][(int) $priority][0][] = $listener;
return $listener;
}
/**
/usr
/local
/vufind
/vendor
/zendframework
/zend-mvc
/src
/Controller
/AbstractController.php
* @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(function ($test) {
return ($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;
/usr
/local
/vufind
/vendor
/zendframework
/zend-mvc
/src
/DispatchListener.php
$return = $this->marshalControllerNotFoundEvent($application::ERROR_CONTROLLER_INVALID, $controllerName, $e, $application, $exception);
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(get_class($controller));
$e->setParam('exception', $caughtException);
$return = $application->getEventManager()->triggerEvent($e)->last();
if (! $return) {
$return = $e->getResult();
}
}
return $this->complete($return, $e);
/usr
/local
/vufind
/vendor
/zendframework
/zend-eventmanager
/src
/EventManager.php
}
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;
}
/usr
/local
/vufind
/vendor
/zendframework
/zend-eventmanager
/src
/EventManager.php
$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))
));
}
$this->events[$eventName][(int) $priority][0][] = $listener;
return $listener;
}
/**
/usr
/local
/vufind
/vendor
/zendframework
/zend-mvc
/src
/Application.php
$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);
$this->completeRequest($event);
return $this;
}
/usr
/local
/vufind
/public
/index.php
if (file_exists('vendor/autoload.php')) {
$loader = include 'vendor/autoload.php';
}
// Support for ZF2_PATH environment variable
if ($zf2Path = getenv('ZF2_PATH')) {
if (isset($loader)) {
$loader->add('Zend', $zf2Path . '/Zend');
} else {
include $zf2Path . '/Zend/Loader/AutoloaderFactory.php';
AutoloaderFactory::factory();
}
}
if (!class_exists('Zend\Loader\AutoloaderFactory')) {
throw new RuntimeException('Unable to load ZF2.');
}
// Run the application!
Zend\Mvc\Application::init(require 'config/application.config.php')->run();
// Handle final profiling details, if necessary:
if ($xhprof) {
$xhprofData = extension_loaded('xhprof') ? xhprof_disable() : tideways_disable();
$xhprofRunId = uniqid();
$suffix = 'vufind';
$dir = ini_get('xhprof.output_dir');
if (empty($dir)) {
$dir = sys_get_temp_dir();
}
file_put_contents("$dir/$xhprofRunId.$suffix.xhprof", serialize($xhprofData));
$url = "$xhprof?run=$xhprofRunId&source=$suffix";
echo "<a href='$url'>Profiler output</a>";
}