2026-02-13T02:31:01+03:00 CRIT: TypeError : VuFind\Controller\AbstractBase::isLocalUrl(): Argument #1 ($url) must be of type string, null given, called in /usr/local/vufind/module/VuFind/src/VuFind/Controller/SearchController.php on line 137
Server Context:
Array
(
    [REDIRECT_SCRIPT_URL] => /Search/Email
    [REDIRECT_SCRIPT_URI] => http://research.kwaretech.com/Search/Email
    [REDIRECT_VUFIND_ENV] => development
    [REDIRECT_VUFIND_LOCAL_DIR] => /usr/local/vufind/local
    [REDIRECT_STATUS] => 200
    [SCRIPT_URL] => /Search/Email
    [SCRIPT_URI] => http://research.kwaretech.com/Search/Email
    [VUFIND_ENV] => development
    [VUFIND_LOCAL_DIR] => /usr/local/vufind/local
    [HTTP_HOST] => research.kwaretech.com
    [HTTP_ACCEPT] => */*
    [HTTP_USER_AGENT] => Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)
    [HTTP_COOKIE] => _opensaml_req_ss%3Amem%3A0b38d702d785d11d9e6bd2137bb4eb7676ca87c782d700c2c99c5f1af43feda7=_ad54409cb4cb42ed4a41100dd8accd47; VUFIND_SESSION=gb47skhpp18v409ics8ikuv21k; VUFIND_SESSION_KEY=XXuPfuFqj8O%2BCou8Mqd%2FlnpJ0yED5eg%2BedMGKmZJSE3G5IAA9FoVUOSHVnYBrNoAiXsJD%2FlQgJ%2B%2F8xX4L9YFYA%3D%3D; language=ar; ui=standard
    [HTTP_ACCEPT_ENCODING] => gzip, br, zstd, deflate
    [HTTP_X_FORWARDED_FOR] => 216.73.216.83
    [HTTP_X_FORWARDED_HOST] => research.kwaretech.com
    [HTTP_X_FORWARDED_SERVER] => research.kwaretech.com
    [HTTP_CONNECTION] => Keep-Alive
    [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    [SERVER_SIGNATURE] => 
Apache/2.4.52 (Ubuntu) Server at research.kwaretech.com Port 80
[SERVER_SOFTWARE] => Apache/2.4.52 (Ubuntu) [SERVER_NAME] => research.kwaretech.com [SERVER_ADDR] => 172.19.0.6 [SERVER_PORT] => 80 [REMOTE_ADDR] => 172.19.0.1 [DOCUMENT_ROOT] => /usr/local/vufind/public [REQUEST_SCHEME] => http [CONTEXT_PREFIX] => [CONTEXT_DOCUMENT_ROOT] => /usr/local/vufind/public [SERVER_ADMIN] => [no address given] [SCRIPT_FILENAME] => /usr/local/vufind/public/index.php [REMOTE_PORT] => 46378 [REDIRECT_URL] => /Search/Email [GATEWAY_INTERFACE] => CGI/1.1 [SERVER_PROTOCOL] => HTTP/1.1 [REQUEST_METHOD] => GET [QUERY_STRING] => [REQUEST_URI] => /Search/Email [SCRIPT_NAME] => /index.php [PHP_SELF] => /index.php [REQUEST_TIME_FLOAT] => 1770939061.1207 [REQUEST_TIME] => 1770939061 ) Backtrace: /usr/local/vufind/module/VuFind/src/VuFind/Controller/SearchController.php line 137 - class = VuFind\Controller\AbstractBase, function = isLocalUrl, args: none. /usr/local/vufind/vendor/laminas/laminas-mvc/src/Controller/AbstractActionController.php line 72 - class = VuFind\Controller\SearchController, function = emailAction, args: none. /usr/local/vufind/vendor/laminas/laminas-eventmanager/src/EventManager.php line 318 - class = Laminas\Mvc\Controller\AbstractActionController, function = onDispatch, args: none. /usr/local/vufind/vendor/laminas/laminas-eventmanager/src/EventManager.php line 176 - class = Laminas\EventManager\EventManager, function = triggerListeners, args: none. /usr/local/vufind/vendor/laminas/laminas-mvc/src/Controller/AbstractController.php line 105 - class = Laminas\EventManager\EventManager, function = triggerEventUntil, args: none. /usr/local/vufind/vendor/laminas/laminas-mvc/src/DispatchListener.php line 117 - class = Laminas\Mvc\Controller\AbstractController, function = dispatch, args: none. /usr/local/vufind/vendor/laminas/laminas-eventmanager/src/EventManager.php line 318 - class = Laminas\Mvc\DispatchListener, function = onDispatch, args: none. /usr/local/vufind/vendor/laminas/laminas-eventmanager/src/EventManager.php line 176 - class = Laminas\EventManager\EventManager, function = triggerListeners, args: none. /usr/local/vufind/vendor/laminas/laminas-mvc/src/Application.php line 319 - class = Laminas\EventManager\EventManager, function = triggerEventUntil, args: none. /usr/local/vufind/public/index.php line 23 - class = Laminas\Mvc\Application, function = run, args: none.
Whoops! There was an error.
TypeError
VuFind\Controller\AbstractBase::isLocalUrl(): Argument #1 ($url) must be of type string, null given, called in /usr/local/vufind/module/VuFind/src/VuFind/Controller/SearchController.php on line 137 TypeError thrown with message "VuFind\Controller\AbstractBase::isLocalUrl(): Argument #1 ($url) must be of type string, null given, called in /usr/local/vufind/module/VuFind/src/VuFind/Controller/SearchController.php on line 137" Stacktrace: #10 TypeError in /usr/local/vufind/module/VuFind/src/VuFind/Controller/AbstractBase.php:894 #9 VuFind\Controller\AbstractBase:isLocalUrl in /usr/local/vufind/module/VuFind/src/VuFind/Controller/SearchController.php:137 #8 VuFind\Controller\SearchController:emailAction in /usr/local/vufind/vendor/laminas/laminas-mvc/src/Controller/AbstractActionController.php:72 #7 Laminas\Mvc\Controller\AbstractActionController:onDispatch in /usr/local/vufind/vendor/laminas/laminas-eventmanager/src/EventManager.php:318 #6 Laminas\EventManager\EventManager:triggerListeners in /usr/local/vufind/vendor/laminas/laminas-eventmanager/src/EventManager.php:176 #5 Laminas\EventManager\EventManager:triggerEventUntil in /usr/local/vufind/vendor/laminas/laminas-mvc/src/Controller/AbstractController.php:105 #4 Laminas\Mvc\Controller\AbstractController:dispatch in /usr/local/vufind/vendor/laminas/laminas-mvc/src/DispatchListener.php:117 #3 Laminas\Mvc\DispatchListener:onDispatch in /usr/local/vufind/vendor/laminas/laminas-eventmanager/src/EventManager.php:318 #2 Laminas\EventManager\EventManager:triggerListeners in /usr/local/vufind/vendor/laminas/laminas-eventmanager/src/EventManager.php:176 #1 Laminas\EventManager\EventManager:triggerEventUntil in /usr/local/vufind/vendor/laminas/laminas-mvc/src/Application.php:319 #0 Laminas\Mvc\Application:run in /usr/local/vufind/public/index.php:23
10
TypeError
/module/VuFind/src/VuFind/Controller/AbstractBase.php894
9
VuFind\Controller\AbstractBase isLocalUrl
/module/VuFind/src/VuFind/Controller/SearchController.php137
8
VuFind\Controller\SearchController emailAction
/vendor/laminas/laminas-mvc/src/Controller/AbstractActionController.php72
7
Laminas\Mvc\Controller\AbstractActionController onDispatch
/vendor/laminas/laminas-eventmanager/src/EventManager.php318
6
Laminas\EventManager\EventManager triggerListeners
/vendor/laminas/laminas-eventmanager/src/EventManager.php176
5
Laminas\EventManager\EventManager triggerEventUntil
/vendor/laminas/laminas-mvc/src/Controller/AbstractController.php105
4
Laminas\Mvc\Controller\AbstractController dispatch
/vendor/laminas/laminas-mvc/src/DispatchListener.php117
3
Laminas\Mvc\DispatchListener onDispatch
/vendor/laminas/laminas-eventmanager/src/EventManager.php318
2
Laminas\EventManager\EventManager triggerListeners
/vendor/laminas/laminas-eventmanager/src/EventManager.php176
1
Laminas\EventManager\EventManager triggerEventUntil
/vendor/laminas/laminas-mvc/src/Application.php319
0
Laminas\Mvc\Application run
/public/index.php23
     * @return \Laminas\Http\Response
     */
    protected function getRefreshResponse(bool $forceGet = false)
    {
        $response = $this->getResponse();
        $response->setStatusCode(205);
        if ($forceGet) {
            $response->getHeaders()->addHeaderLine('X-VuFind-Refresh-Method', 'GET');
        }
        return $response;
    }
 
    /**
     * Is the provided URL local to this instance?
     *
     * @param string $url URL to check
     *
     * @return bool
     */
    protected function isLocalUrl(string $url): bool
    {
        $baseUrlNorm = $this->normalizeUrlForComparison($this->getServerUrl('home'));
        return str_starts_with($this->normalizeUrlForComparison($url), $baseUrlNorm);
    }
}
 
Arguments
  1. "VuFind\Controller\AbstractBase::isLocalUrl(): Argument #1 ($url) must be of type string, null given, called in /usr/local/vufind/module/VuFind/src/VuFind/Controller/SearchController.php on line 137"
    
    }
 
    /**
     * Email action - Allows the email form to appear.
     *
     * @return mixed
     */
    public function emailAction()
    {
        // If a URL was explicitly passed in, use that; otherwise, try to
        // find the HTTP referrer.
        $mailer = $this->getService(\VuFind\Mailer\Mailer::class);
        $view = $this->createEmailViewModel(null, $mailer->getDefaultLinkSubject());
        $mailer->setMaxRecipients($view->maxRecipients);
        // Set up Captcha
        $view->useCaptcha = $this->captcha()->active('email');
        $view->url = $this->params()->fromPost('url')
            ?? $this->params()->fromQuery('url')
            ?? $this->getRequest()->getServer()->get('HTTP_REFERER');
        if (!$this->isLocalUrl($view->url)) {
            throw new \Exception('Unexpected value passed to emailAction: ' . $view->url);
        }
 
        $emailActionSettings = $this->getService(\VuFind\Config\AccountCapabilities::class)->getEmailActionSetting();
        if ($emailActionSettings === 'disabled') {
            throw new ForbiddenException('Email action disabled');
        }
        // Force login if necessary:
        if (
            $emailActionSettings !== 'enabled'
            && !$this->getUser()
        ) {
            return $this->forceLogin(null, ['emailurl' => $view->url]);
        }
 
        // Check if we have a URL in login followup data -- this should override
        // any existing referer to avoid emailing a login-related URL!
        $followupUrl = $this->followup()->retrieveAndClear('emailurl');
        if (!empty($followupUrl)) {
            $view->url = $followupUrl;
     */
    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();
}
 

Environment & details:

empty
empty
empty
Key Value
_opensaml_req_ss%3Amem%3A0b38d702d785d11d9e6bd2137bb4eb7676ca87c782d700c2c99c5f1af43feda7
"_ad54409cb4cb42ed4a41100dd8accd47"
VUFIND_SESSION
"gb47skhpp18v409ics8ikuv21k"
VUFIND_SESSION_KEY
"XXuPfuFqj8O+Cou8Mqd/lnpJ0yED5eg+edMGKmZJSE3G5IAA9FoVUOSHVnYBrNoAiXsJD/lQgJ+/8xX4L9YFYA=="
language
"ar"
ui
"standard"
Key Value
__Laminas
array:4 [
  "_REQUEST_ACCESS_TIME" => 1770939061.1527
  "_VALID" => array:1 [
    "Laminas\Session\Validator\Id" => "gb47skhpp18v409ics8ikuv21k"
  ]
  "FlashMessenger" => array:1 [
    "EXPIRE_HOPS" => array:2 [
      "hops" => 0
      "ts" => 1770939060.9696
    ]
  ]
  "csrf" => array:1 [
    "EXPIRE" => 1770939360
  ]
]
SessionState
Laminas\Stdlib\ArrayObject {#937}
Folio_kware
Laminas\Stdlib\ArrayObject {#938}
Followup
Laminas\Stdlib\ArrayObject {#939}
FlashMessenger
Laminas\Stdlib\ArrayObject {#940}
csrf
Laminas\Stdlib\ArrayObject {#941}
SessionHelper
Laminas\Stdlib\ArrayObject {#942}
Key Value
REDIRECT_SCRIPT_URL
"/Search/Email"
REDIRECT_SCRIPT_URI
"http://research.kwaretech.com/Search/Email"
REDIRECT_VUFIND_ENV
"development"
REDIRECT_VUFIND_LOCAL_DIR
"/usr/local/vufind/local"
REDIRECT_STATUS
"200"
SCRIPT_URL
"/Search/Email"
SCRIPT_URI
"http://research.kwaretech.com/Search/Email"
VUFIND_ENV
"development"
VUFIND_LOCAL_DIR
"/usr/local/vufind/local"
HTTP_HOST
"research.kwaretech.com"
HTTP_ACCEPT
"*/*"
HTTP_USER_AGENT
"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)"
HTTP_COOKIE
"_opensaml_req_ss%3Amem%3A0b38d702d785d11d9e6bd2137bb4eb7676ca87c782d700c2c99c5f1af43feda7=_ad54409cb4cb42ed4a41100dd8accd47; VUFIND_SESSION=gb47skhpp18v409ics8ikuv21k; VUFIND_SESSION_KEY=XXuPfuFqj8O%2BCou8Mqd%2FlnpJ0yED5eg%2BedMGKmZJSE3G5IAA9FoVUOSHVnYBrNoAiXsJD%2FlQgJ%2B%2F8xX4L9YFYA%3D%3D; language=ar; ui=standard"
HTTP_ACCEPT_ENCODING
"gzip, br, zstd, deflate"
HTTP_X_FORWARDED_FOR
"216.73.216.83"
HTTP_X_FORWARDED_HOST
"research.kwaretech.com"
HTTP_X_FORWARDED_SERVER
"research.kwaretech.com"
HTTP_CONNECTION
"Keep-Alive"
PATH
"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
SERVER_SIGNATURE
"<address>Apache/2.4.52 (Ubuntu) Server at research.kwaretech.com Port 80</address>\n"
SERVER_SOFTWARE
"Apache/2.4.52 (Ubuntu)"
SERVER_NAME
"research.kwaretech.com"
SERVER_ADDR
"172.19.0.6"
SERVER_PORT
"80"
REMOTE_ADDR
"172.19.0.1"
DOCUMENT_ROOT
"/usr/local/vufind/public"
REQUEST_SCHEME
"http"
CONTEXT_PREFIX
""
CONTEXT_DOCUMENT_ROOT
"/usr/local/vufind/public"
SERVER_ADMIN
"[no address given]"
SCRIPT_FILENAME
"/usr/local/vufind/public/index.php"
REMOTE_PORT
"46378"
REDIRECT_URL
"/Search/Email"
GATEWAY_INTERFACE
"CGI/1.1"
SERVER_PROTOCOL
"HTTP/1.1"
REQUEST_METHOD
"GET"
QUERY_STRING
""
REQUEST_URI
"/Search/Email"
SCRIPT_NAME
"/index.php"
PHP_SELF
"/index.php"
REQUEST_TIME_FLOAT
1770939061.1207
REQUEST_TIME
1770939061
empty
0. Whoops\Handler\PrettyPageHandler