HEX
Server: Apache
System: Linux s198.coreserver.jp 5.15.0-151-generic #161-Ubuntu SMP Tue Jul 22 14:25:40 UTC 2025 x86_64
User: nagasaki (10062)
PHP: 7.1.33
Disabled: NONE
Upload Files
File: /virtual/nagasaki/public_html/ec/src/Eccube/EventListener/RequestDumpListener.php
<?php

namespace Eccube\EventListener;

use Eccube\Application;
use Monolog\Logger;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * リクエストログ出力ため Listener
 *
 * ログ出力を除外したいキーは log.yml の exclude_keys で設定します.
 * addExcludeKey(), removeExcludeKey() でも設定できます.
 *
 * @author Kentaro Ohkouchi
 */
class RequestDumpListener implements EventSubscriberInterface
{
    private $app;
    private $excludeKeys;

    /**
     * Constructor function.
     *
     * @param Application $app
     */
    public function __construct(Application $app)
    {
        $this->app = $app;
        $this->excludeKeys = $app['config']['log']['exclude_keys'];
    }

    /**
     * Kernel request listener callback.
     *
     * @param GetResponseEvent $event
     */
    public function onKernelRequest(GetResponseEvent $event)
    {
        if (!$event->isMasterRequest()) {
            return;
        }
        $log = '** before *****************************************:'.PHP_EOL;
        $request = $event->getRequest();
        $log .= $this->logRequest($request);
        $Session = $request->getSession();
        if ($request->hasSession()) {
            $log .= $this->logSession($Session);
        }
        $this->app->log($log, array(), Logger::DEBUG);
        log_debug($log);
    }

    /**
     * Kernel response listener callback.
     *
     * @param FilterResponseEvent $event
     */
    public function onResponse(FilterResponseEvent $event)
    {
        if (!$event->isMasterRequest()) {
            return;
        }
        $log = '** after *****************************************:'.PHP_EOL;
        $response = $event->getResponse();
        $log .= $this->logResponse($response);
        $request = $event->getRequest();
        $log .= $this->logRequest($request);
        $Session = $request->getSession();
        if ($request->hasSession()) {
            $log .= $this->logSession($Session);
        }
        $this->app->log($log, array(), Logger::DEBUG);
        log_debug($log);
    }

    /**
     * Return the events to subscribe to.
     *
     * @return array
     */
    public static function getSubscribedEvents()
    {
        return array(
            KernelEvents::REQUEST => 'onKernelRequest',
            KernelEvents::RESPONSE => 'onResponse',
        );
    }

    /**
     * ログ出力を除外するキーを追加します.
     *
     * @param string $key 除外対象のキー
     */
    protected function addExcludeKey($key)
    {
        $this->excludeKeys[] = $key;
    }

    /**
     * ログ出力を除外するキーを削除します.
     *
     * @param string $key 削除対象のキー
     */
    protected function removeExcludeKey($key)
    {
        if (array_key_exists($key, $this->excludeKeys)) {
            unset($this->excludeKeys[$key]);
        }
    }

    /**
     * Request のログを出力する.
     *
     * @param Request $request
     * @return string Request のログ
     */
    protected function logRequest(Request $request)
    {
        $log = '';
        $log .= $this->logKeyValuePair('REMOTE_ADDR', $request->getClientIp());
        $log .= $this->logKeyValuePair('SCRIPT_NAME', $request->getScriptName());
        $log .= $this->logKeyValuePair('PATH_INFO', $request->getPathInfo());
        $log .= $this->logKeyValuePair('BASE_PATH', $request->getBasePath());
        $log .= $this->logKeyValuePair('BASE_URL', $request->getBaseUrl());
        $log .= $this->logKeyValuePair('SCHEME', $request->getScheme());
        $log .= $this->logKeyValuePair('REMOTE_USER', $request->getUser());
        $log .= $this->logKeyValuePair('HTTP_HOST', $request->getSchemeAndHttpHost());
        $log .= $this->logKeyValuePair('REQUEST_URI', $request->getRequestUri());
        $log .= $this->logKeyValuePair('METHOD', $request->getRealMethod());
        $log .= $this->logKeyValuePair('LOCALE', $request->getLocale());
        // $log .= $this->logArray($request->server->all(), '[server]'); // 大量にログ出力される...
        $log .= $this->logArray($request->headers->all(), '[header]');
        $log .= $this->logArray($request->query->all(), '[get]');
        $log .= $this->logArray($request->request->all(), '[post]');
        $log .= $this->logArray($request->attributes->all(), '[attributes]');
        $log .= $this->logArray($request->cookies->all(), '[cookie]');
        $log .= $this->logArray($request->files->all(), '[files]');

        return $log;
    }

    /**
     * Response のログを出力する.
     *
     * @param Response $response
     * @return string Response のログ
     */
    protected function logResponse(Response $response)
    {
        $log = '';
        $log .= $this->logKeyValuePair('HTTP_STATUS', $response->getStatusCode());

        return $log;
    }

    /**
     * Session のログを出力する.
     */
    protected function logSession(SessionInterface $Session)
    {
        return $this->logArray($Session->all(), '[session]');
    }

    /**
     * 配列をログ出力する.
     */
    protected function logArray(array $values, $prefix = '')
    {
        $log = '';
        foreach ($values as $key => $val) {
            $log .= $this->logKeyValuePair($key, $val, $prefix);
        }

        return $log;
    }

    /**
     * キーと値のペアをログ出力する.
     *
     * 除外キーに該当する値は, マスクをかける
     */
    protected function logKeyValuePair($key, $value, $prefix = '')
    {
        if (in_array($key, $this->excludeKeys)) {
            return '';
        }
        if (is_null($value) || is_scalar($value) || (is_object($value) && method_exists($value, '__toString'))) {
            $copy_value = $value;
        } elseif (is_object($value)) {
            try {
                $copy_value = '[object '.serialize($value).']';
            } catch (\Exception $e) {
                return $e->getMessage().PHP_EOL;
            }
        } else {
            $copy_value = $value;
            if (is_array($copy_value)) {
                foreach ($copy_value as $key => &$val) {
                    if (in_array($key, $this->excludeKeys)
                        && $prefix != '[header]') { // XXX header にもマスクがかかってしまう
                        $val = '******';
                    }
                }
            }
            try {
                $copy_value = '['.serialize($copy_value).']';
            } catch (\Exception $e) {
                return $e->getMessage().PHP_EOL;
            }
        }

        return '  '.$prefix.' '.$key.'='.$copy_value.PHP_EOL;
    }
}