<?php
/**
 * SeekQuarry/Yioop --
 * Open Source Pure PHP Search Engine, Crawler, and Indexer
 *
 * Copyright (C) 2009 - 2026  Chris Pollett chris@pollett.org
 *
 * LICENSE:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * END LICENSE
 *
 * @author Chris Pollett chris@pollett.org
 * @license https://www.gnu.org/licenses/ GPL3
 * @link https://www.seekquarry.com/
 * @copyright 2009 - 2026
 * @filesource
 */
namespace seekquarry\yioop\library;

/**
 * RequestScope holds a value worked out once for one request, the way a
 * static holds one worked out once for one process.
 *
 * A static is the usual way to keep something costly, such as the locale
 * a reader wants, so it is worked out once rather than on every call.
 * Under another web server that is safe, since each request is its own
 * process. Under Yioop's own web server one process answers many
 * requests, and it may set a request aside part way through and serve
 * another before picking the first up again. A static then carries one
 * reader's answer into another reader's page.
 *
 * The values here are kept in $_SERVER, which that server saves and puts
 * back around every such handover, so each request sees only its own.
 * Reading one costs an array lookup, as a static does. Under a server
 * that gives each request its own process, $_SERVER is fresh for each
 * one, so the behavior is the same.
 *
 * Use it for anything worked out from what a request carries: the
 * locale, the signed-in reader, the group a domain serves. Do not use it
 * for something that is the same for every reader, such as a loaded
 * table or a parsed settings file; a plain static is right for those and
 * costs less.
 *
 * @author Chris Pollett
 */
class RequestScope
{
    /**
     * WHERE_KEPT is the name under which every value of this kind is
     * kept in $_SERVER. One name holds them all, so the server's saving
     * and restoring carries the whole set with one entry.
     */
    const WHERE_KEPT = "YIOOP_REQUEST_SCOPE";
    /**
     * get gives back the value kept for this request under a name, or a
     * value of the caller's choosing where nothing is kept.
     *
     * A caller uses this before working a costly value out, and calls
     * set with the answer, so the work happens once for each request
     * rather than once for each call.
     *
     * @param string $name what the value is kept under
     * @param mixed $missing what to give back where nothing is kept
     * @return mixed the value kept for this request, or $missing
     */
    public static function get($name, $missing = null)
    {
        if (!isset($_SERVER[self::WHERE_KEPT][$name])) {
            return $missing;
        }
        return $_SERVER[self::WHERE_KEPT][$name];
    }
    /**
     * set keeps a value for the rest of this request under a name. A
     * later request, even one the server is already part way through,
     * has its own set and never sees this one.
     *
     * @param string $name what to keep the value under
     * @param mixed $value the value to keep
     * @return mixed the value that was kept, so a caller may write
     *     return RequestScope::set($name, $worked_out);
     */
    public static function set($name, $value)
    {
        if (!isset($_SERVER[self::WHERE_KEPT])) {
            $_SERVER[self::WHERE_KEPT] = [];
        }
        $_SERVER[self::WHERE_KEPT][$name] = $value;
        return $value;
    }
}
