PHP Classes

File: src/Response/Manager/ResponseManager.php

Recommend this page to a friend!
  Packages of Thierry Feuzeu   Jaxon   src/Response/Manager/ResponseManager.php   Download  
File: src/Response/Manager/ResponseManager.php
Role: Class source
Content type: text/plain
Description: Class source
Class: Jaxon
Call PHP classes from JavaScript using AJAX
Author: By
Last change:
Date: 1 year ago
Size: 10,157 bytes
 

Contents

Class file image Download
<?php

/**
 * ResponseManager.php - Jaxon Response Manager
 *
 * This class stores and tracks the response that will be returned after processing a request.
 * The Response Manager represents a single point of contact for working with <AbstractResponsePlugin> objects.
 *
 * @package jaxon-core
 * @author Jared White
 * @author J. Max Wilson
 * @author Joseph Woolley
 * @author Steffen Konerow
 * @author Thierry Feuzeu <thierry.feuzeu@gmail.com>
 * @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson
 * @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White  & J. Max Wilson
 * @copyright 2016 Thierry Feuzeu <thierry.feuzeu@gmail.com>
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
 * @link https://github.com/jaxon-php/jaxon-core
 */

namespace Jaxon\Response\Manager;

use Jaxon\App\I18n\Translator;
use Jaxon\Exception\AppException;
use Jaxon\Di\Container;
use Jaxon\Response\AbstractResponse;
use Jaxon\Response\AjaxResponse;
use Jaxon\Response\NodeResponse;
use Jaxon\Response\Response;
use Jaxon\Script\Call\JxnCall;
use Closure;
use JsonSerializable;

use function array_filter;
use function array_merge;
use function count;
use function trim;

class ResponseManager
{
    /**
     * The current response object that will be sent back to the browser
     * once the request processing phase is complete
     *
     * @var AbstractResponse
     */
    private $xResponse = null;

    /**
     * The error message
     *
     * @var string
     */
    private $sErrorMessage = '';

    /**
     * The debug messages
     *
     * @var array
     */
    private $aDebugMessages = [];

    /**
     * The commands that will be sent to the browser in the response
     *
     * @var array
     */
    protected $aCommands = [];

    /**
     * If the commands beeing added are to be confirmed
     *
     * @var bool
     */
    private $bOnConfirm = false;

    /**
     * The commands that will be sent to the browser in the response
     *
     * @var array
     */
    private $aConfirmCommands = [];

    /**
     * @param Container $di
     * @param Translator $xTranslator
     * @param string $sCharacterEncoding
     */
    public function __construct(private Container $di,
        private Translator $xTranslator, private string $sCharacterEncoding)
    {}

    /**
     * Get the configured character encoding
     *
     * @return string
     */
    public function getCharacterEncoding(): string
    {
        return $this->sCharacterEncoding;
    }

    /**
     * Convert to string
     *
     * @param mixed $xData
     *
     * @return string
     */
    public function str($xData): string
    {
        return trim((string)$xData, " \t\n");
    }

    /**
     * Get a translated string
     *
     * @param string $sText The key of the translated string
     * @param array $aPlaceHolders The placeholders of the translated string
     *
     * @return string
     */
    public function trans(string $sText, array $aPlaceHolders = []): string
    {
        return $this->xTranslator->trans($sText, $aPlaceHolders);
    }

    /**
     * Set the error message
     *
     * @param string $sErrorMessage
     *
     * @return void
     */
    public function setErrorMessage(string $sErrorMessage): void
    {
        $this->sErrorMessage = $sErrorMessage;
    }

    /**
     * Get the error message
     *
     * @return string
     */
    public function getErrorMessage(): string
    {
        return $this->sErrorMessage;
    }

    /**
     * Get the commands in the response
     *
     * @return array
     */
    public function getCommands(): array
    {
        return $this->aCommands;
    }

    /**
     * Get the number of commands in the response
     *
     * @return int
     */
    public function getCommandCount(): int
    {
        return count($this->aCommands);
    }

    /**
     * Clear all the commands already added to the response
     *
     * @return void
     */
    public function clearCommands(): void
    {
        $this->aCommands = [];
    }

    /**
     * @param array|JsonSerializable $aArgs    The command arguments
     * @param bool $bRemoveEmpty    If true, remove empty arguments
     *
     * @return array
     */
    private function getCommandArgs(array|JsonSerializable $aArgs, bool $bRemoveEmpty = false): array
    {
        if(!$bRemoveEmpty)
        {
            return $aArgs;
        }
        return array_filter($aArgs, function($xArg) {
            return !empty($xArg);
        });
    }

    /**
     * Add a response command to the array of commands
     *
     * @param string $sName    The command name
     * @param array|JsonSerializable $aArgs    The command arguments
     * @param bool $bRemoveEmpty
     *
     * @return Command
     */
    public function addCommand(string $sName, array|JsonSerializable $aArgs,
        bool $bRemoveEmpty = false): Command
    {
        $xCommand = new Command([
            'name' => $this->str($sName),
            'args' => $this->getCommandArgs($aArgs, $bRemoveEmpty),
        ]);
        if($this->bOnConfirm)
        {
            $this->aConfirmCommands[] = $xCommand;
        }
        else
        {
            $this->aCommands[] = $xCommand;
        }
        return $xCommand;
    }

    /**
     * Response command that prompts user with [ok] [cancel] style message box
     *
     * The provided closure will be called with a response object as unique parameter.
     * If the user clicks cancel, the response commands defined in the closure will be skipped.
     *
     * @param string $sName     The command name
     * @param Closure $fConfirm A closure that defines the commands that can be skipped
     * @param string $sQuestion The question to ask to the user
     * @param array $aArgs      The arguments for the placeholders in the question
     *
     * @throws AppException
     *
     * @return self
     */
    public function addConfirmCommand(string $sName, Closure $fConfirm,
        string $sQuestion, array $aArgs = []): self
    {
        if($this->bOnConfirm)
        {
            throw new AppException($this->xTranslator->trans('errors.app.confirm.nested'));
        }
        $this->bOnConfirm = true;
        $fConfirm();
        $this->bOnConfirm = false;
        if(($nCommandCount = count($this->aConfirmCommands)) > 0)
        {
            $aCommand = $this->di->getDialogCommand()->confirm($this->str($sQuestion), $aArgs);
            $aCommand['count'] = $nCommandCount;
            // The confirm command must be inserted before the commands to be confirmed.
            $this->addCommand($sName, $aCommand);
            $this->aCommands = array_merge($this->aCommands, $this->aConfirmCommands);
            $this->aConfirmCommands = [];
        }
        return $this;
    }

    /**
     * Add a command to display an alert message to the user
     *
     * @param string $sName     The command name
     * @param string $sMessage  The message to be displayed
     * @param array $aArgs      The arguments for the placeholders in the message
     *
     * @throws AppException
     *
     * @return self
     */
    public function addAlertCommand(string $sName, string $sMessage, array $aArgs = []): self
    {
        $aCommand = $this->di->getDialogCommand()->info($this->str($sMessage), $aArgs);
        $this->addCommand($sName, $aCommand);
        return $this;
    }

    /**
     * Get the response to the Jaxon request
     *
     * @return Response
     */
    public function getResponse(): Response
    {
        return $this->di->getResponse();
    }

    /**
     * Create a new Jaxon response
     *
     * @return Response
     */
    public function newResponse(): Response
    {
        return $this->xResponse = $this->di->newResponse();
    }

    /**
     * Get the Jaxon ajax response returned 
     *
     * @return AjaxResponse
     */
    public function ajaxResponse(): AjaxResponse
    {
        return $this->xResponse ?: $this->di->getResponse();
    }

    /**
     * Create a new reponse for a Jaxon component
     *
     * @param JxnCall $xJxnCall
     *
     * @return NodeResponse
     */
    public function newNodeResponse(JxnCall $xJxnCall): NodeResponse
    {
        return $this->di->newNodeResponse($xJxnCall);
    }

    /**
     * Appends a debug message on the end of the debug message queue
     *
     * Debug messages will be sent to the client with the normal response
     * (if the response object supports the sending of debug messages, see: <AbstractResponsePlugin>)
     *
     * @param string $sMessage    The debug message
     *
     * @return void
     */
    public function debug(string $sMessage): void
    {
        $this->aDebugMessages[] = $sMessage;
    }

    /**
     * Clear the response and appends a debug message on the end of the debug message queue
     *
     * @param string $sMessage The debug message
     *
     * @return void
     */
    public function error(string $sMessage): void
    {
        $this->clearCommands();
        $this->debug($sMessage);
    }

    /**
     * Prints the debug messages into the current response object
     *
     * @return void
     */
    public function printDebug()
    {
        foreach($this->aDebugMessages as $sMessage)
        {
            $this->addCommand('script.debug', ['message' => $this->str($sMessage)]);
        }
        // $this->aDebugMessages = [];
    }

    /**
     * Get the content type of the HTTP response
     *
     * @return string
     */
    public function getContentType(): string
    {
        return empty($this->sCharacterEncoding) ? $this->getResponse()->getContentType() :
            $this->getResponse()->getContentType() . '; charset="' . $this->sCharacterEncoding . '"';
    }

    /**
     * Get the JSON output of the response
     *
     * @return string
     */
    public function getOutput(): string
    {
        return $this->getResponse()->getOutput();
    }

    /**
     * Get the debug messages
     *
     * @return array
     */
    public function getDebugMessages(): array
    {
        return $this->aDebugMessages;
    }
}