seacms-app/tests/AppTest.php
2023-04-04 09:36:19 +02:00

346 lines
13 KiB
PHP

<?php
/**
* SPDX-License-Identifier: EUPL-1.2
* Authors: see /README.md
*/
namespace SeaCMS\App\Test;
use PHPUnit\Framework\TestCase;
use SeaCMS\App;
use SeaCMS\App\TestBaseUrl;
use SeaCMS\App\TestBaseUrlException;
use Throwable;
final class AppTest extends TestCase {
/**
* register error handlers
*/
public function registerErrorHandler()
{
if (empty($GLOBALS['errrHandlerSet'])){
$GLOBALS['errrHandlerSet'] = "1";
$displayErrors = true;
set_error_handler(function(
int $errno,
string $errstr,
?string $errfile = null,
?int $errline = null,
?array $errcontext = null
) use (&$displayErrors){
if ($displayErrors){
echo "\nError $errstr ($errno)\nIn file $errfile\nLine : $errline\n";
}
});
register_shutdown_function(function (){
$lastErr = error_get_last();
if (!is_null($lastErr)){
echo "\nAn error occured\n".json_encode($lastErr)."\n";
}
});
}
}
/**
* @dataProvider apiRewriteProvider
* @covers App::update_SERVERIfNeeded
* @param string $rootFolder
* @param string $filePath
* @param string $shortScriptName
* @param string $queryString
* @param string $waitedBaseUrl
* @param string $waitedPageId
* @param string $waitedPageUrl
* @param string $waitedThemesUrl
* @param string $waitedPluginsUrl
*/
public function testApiRewrite(
string $rootFolder,
string $filePath,
string $shortScriptName,
string $queryString,
string $waitedBaseUrl,
string $waitedPageId,
string $waitedPageUrl,
string $waitedThemesUrl,
string $waitedPluginsUrl,
): void
{
$this->registerErrorHandler();
$this->saveSERVER();
$this->defineServer(
true,
$filePath,
$shortScriptName,
$queryString
);
$app = new App($rootFolder,new TestBaseUrl());
$thrown = false;
$foundTh = null;
try {
$output = $app->runPico();
} catch (TestBaseUrlException $th) {
$thrown = true;
$foundTh = $th;
} catch (Throwable $th){
}
$sn = $_SERVER['SCRIPT_NAME'];
$cwd = getcwd();
$this->revertSERVER();
$this->assertTrue($thrown,"TestBaseUrlException not found");
$this->assertEquals($waitedBaseUrl,$foundTh->getBaseUrl(),"Not same baseUrl ($sn)");
$this->assertEquals("$cwd/vendor/picocms/plugins/",$foundTh->getPluginDir(),"Not same pluginDir");
$this->assertEquals("$cwd/vendor/picocms/themes/",$foundTh->getThemeDir(),"Not same themeDir");
$this->assertEquals("$cwd/",$foundTh->getRootDir(),"Not same rootDir");
$currentPage = $foundTh->getcurrentPage();
$this->assertIsArray($currentPage,"Current Page should be an array");
$this->assertArrayHasKey('id',$currentPage,"Current Page should be an array with key 'id'");
$this->assertEquals($waitedPageId,$currentPage['id'],"Not waited page's id");
$this->assertArrayHasKey('url',$currentPage,"Current Page should be an array with key 'url'");
$this->assertEquals($waitedPageUrl,$currentPage['url'],"Not waited page's url");
$twigVariables = $foundTh->getTwigVariables();
$this->assertIsArray($twigVariables,"Twigvariables should be an array");
$this->assertArrayHasKey('themes_url',$twigVariables,"Twigvariables should be an array with key 'themes_url'");
$this->assertEquals($waitedThemesUrl,$twigVariables['themes_url'],"Not waited themes_url");
$this->assertArrayHasKey('plugins_url',$twigVariables,"Twigvariables should be an array with key 'plugins_url'");
$this->assertEquals($waitedPluginsUrl,$twigVariables['plugins_url'],"Not waited plugins_url");
}
public function apiRewriteProvider()
{
$data = [];
$this->prepareAPage($data,'','content','index');
$this->prepareAPage($data,'','content','sub/index');
$this->prepareAPage($data,'','content','theme');
$this->prepareAPage($data,'','sites/default','index');
$this->prepareAPage($data,'','sites/default','sub/index');
$this->prepareAPage($data,'','sites/default','theme');
$this->prepareAPage($data,'/sea','content','index');
$this->prepareAPage($data,'/sea','content','sub/index');
$this->prepareAPage($data,'/sea','content','theme');
$this->prepareAPage($data,'/sea','sites/default','index');
$this->prepareAPage($data,'/sea','sites/default','sub/index');
$this->prepareAPage($data,'/sea','sites/default','theme');
return $data;
}
protected function prepareAPage(
array &$data,
string $baseScriptName,
string $rootFolder,
string $waitedPageId
)
{
$baseUrl = 'http://localhost'.$baseScriptName.'/';
// tests
$isIndex = ($waitedPageId == 'index');
$isSubIndex = (substr($waitedPageId,-strlen('/index')) == '/index');
// intermediate variables
$pageIdInUrl = $isIndex ? '' : ($isSubIndex ? substr($waitedPageId,0,-strlen('/index')) : $waitedPageId) ;
$waitedPageEndUrl = $pageIdInUrl;
foreach([false,true] as $viaQueryString){
$queryString = $viaQueryString ? $pageIdInUrl : '';
$queryStringWithQuestion = ($viaQueryString && !empty($pageIdInUrl)) ? "?$pageIdInUrl" : '';
$formattedQueryString = str_replace('/','%2F',$pageIdInUrl);
foreach (['','index.php'] as $endShortScriptName) {
// $filePath from getcwd
if ($rootFolder == 'content' && $viaQueryString){
// test also from base
$filePath = 'index.php';
$shortScriptName = "$baseScriptName/$endShortScriptName";
$name = $rootFolder.$shortScriptName.$queryStringWithQuestion.'*';
$waitedBaseUrl = "$baseUrl/content/";
$this->prepareData($baseUrl,$data,$name,$rootFolder,$filePath,$shortScriptName,$queryString,$waitedBaseUrl,$waitedPageId,$waitedPageEndUrl);
}
foreach([false,true] as $viaScriptName){
$folderInScriptName = ($viaScriptName && !empty($pageIdInUrl)) ? "$pageIdInUrl/" : '';
$folderInScriptFileName = ($viaScriptName && !empty($pageIdInUrl)) ? "/$pageIdInUrl" :'' ;
foreach ([false,true] as $withRewrite) {
if ($viaQueryString || $endShortScriptName){
$filePath = "$rootFolder$folderInScriptFileName/index.php";
$shortScriptName = $withRewrite
? "$baseScriptName/$folderInScriptName$endShortScriptName"
: "$baseScriptName/$rootFolder/$folderInScriptName$endShortScriptName";
$waitedBaseUrl = $withRewrite
? $baseUrl
: "$baseUrl$rootFolder/";
$name = $rootFolder.$shortScriptName.$queryStringWithQuestion.($withRewrite ? ' R': '');
$this->prepareData($baseUrl,$data,$name,$rootFolder,$filePath,$shortScriptName,$queryString,$waitedBaseUrl,$waitedPageId,$waitedPageEndUrl);
}
}
}
}
}
}
protected function prepareData(
string $baseUrl,
array &$data,
string $name,
string $rootFolder,
string $filePath,
string $shortScriptName,
string $queryString,
string $waitedBaseUrl,
string $waitedPageId,
string $waitedPageEndUrl
)
{
$waitedPageUrl = $waitedBaseUrl.$waitedPageEndUrl;
$waitedThemesUrl = $baseUrl.'vendor/picocms/themes';
$waitedPluginsUrl = $baseUrl.'vendor/picocms/plugins';
$data[$name] = compact([
'rootFolder',
'filePath',
'shortScriptName',
'queryString',
'waitedBaseUrl',
'waitedPageId',
'waitedPageUrl',
'waitedThemesUrl',
'waitedPluginsUrl'
]);
}
/**
* define $_SERVER because fastcgi not run in CLI
* @param bool $reset reset previous $_SERVER
* @param string $filePath realpath of current script file
* @param string $shortScriptName uri path of current script file
* @param string $queryString wanted query string
* @param string $method
* @param string $pathInfo
*/
public function defineServer(
bool $reset,
string $filePath,
string $shortScriptName,
string $queryString,
string $method = 'GET',
string $pathInfo = ''
)
{
if (is_file($filePath)){
if (!is_array($_SERVER) || $reset){
$new = [];
if (is_array($_SERVER)){
foreach(['SERVER_SOFTWARE','SERVER_PROTOCOL','GATEWAY_INTERFACE'] as $key){
if (array_key_exists($key,$_SERVER)){
$new[$key] = $_SERVER[$key];
}
}
}
$_SERVER = $new;
}
$_SERVER['QUERY_STRING'] = $queryString;
$_SERVER['REQUEST_METHOD'] = in_array($method,['GET','POST','PUT','DELETE','HEAD']) ? $method : 'GET';
// $_SERVER['CONTENT_TYPE'] = 'not defined';
// $_SERVER['CONTENT_LENGTH'] = 'not defined';
$documentRoot = dirname(realpath($filePath));
$fileName = basename(realpath($filePath));
$documentRootShort = (substr($documentRoot,-strlen(DIRECTORY_SEPARATOR)) != DIRECTORY_SEPARATOR)
? $documentRoot
: substr($documentRoot,0,-strlen(DIRECTORY_SEPARATOR));
$documentRootFull = $documentRootShort.DIRECTORY_SEPARATOR;
$scriptName = (basename($shortScriptName) == $fileName)
? $shortScriptName
: $shortScriptName.((empty($shortScriptName) || substr($shortScriptName,-1) == '/') ? '' : '/').$fileName;
$hashPos = strpos($queryString,'#');
$queryStringWithoutHash =
(empty($queryString) || ($hashPos === 0))
? ''
: (
($hashPos === false)
? "?$queryString"
: '?'.sustr($queryString,0,$hashPos+1)
);
$_SERVER['SCRIPT_FILENAME'] = $documentRootFull.$fileName;
$_SERVER['SCRIPT_NAME'] = $scriptName;
$_SERVER['PHP_SELF'] = $scriptName.$pathInfo;
$_SERVER['PATH_INFO'] = $pathInfo;
$_SERVER['ORIG_PATH_INFO'] = $pathInfo;
$_SERVER['PATH_TRANSLATED'] = $documentRootShort.$pathInfo;
if (substr($shortScriptName,-1) == '/'){
if (!empty($pathInfo) && substr($pathInfo,0,1) == '/'){
$_SERVER['DOCUMENT_URI'] = $shortScriptName.substr($pathInfo,1);
} else {
$_SERVER['DOCUMENT_URI'] = $shortScriptName.$pathInfo;
}
} else if (empty($pathInfo) || substr($pathInfo,0,1) == '/'){
$_SERVER['DOCUMENT_URI'] = $shortScriptName.$pathInfo;
} else {
$_SERVER['DOCUMENT_URI'] = $shortScriptName.'/'.$pathInfo;
}
$_SERVER['REQUEST_URI'] = $_SERVER['DOCUMENT_URI'].$queryStringWithoutHash;
$_SERVER['DOCUMENT_ROOT'] = $documentRootShort;
$_SERVER['REMOTE_ADDR'] = '127.0.0.1'; // forced
$_SERVER['REMOTE_PORT'] = '80'; // forced
$_SERVER['SERVER_ADDR'] = '127.0.0.1'; // forced
$_SERVER['SERVER_PORT'] = '80'; // forced
$_SERVER['SERVER_NAME'] = 'localhost'; // forced
$_SERVER['HTTPS'] = null; // forced
$_SERVER['REQUEST_TIME'] = time();
}
}
/**
* save previous $_SERVER in $GLOBALS if existing
*/
public function saveSERVER()
{
if (!isset($GLOBALS['savedSERVER'])){
$GLOBALS['savedSERVER'] = [
'saved' => false,
'value' => null
];
}
if (!$GLOBALS['savedSERVER']['saved']){
if (!isset($_SERVER)){
$GLOBALS['savedSERVER']['value'] = null;
$GLOBALS['savedSERVER']['saved'] = true;
} else {
$GLOBALS['savedSERVER']['value'] = $_SERVER;
$GLOBALS['savedSERVER']['saved'] = true;
}
}
}
/**
* revert previous $_SERVER in $GLOBALS if existing
*/
public function revertSERVER()
{
if (isset($GLOBALS['savedSERVER']['saved']) && $GLOBALS['savedSERVER']['saved']){
if (is_null($GLOBALS['savedSERVER']['value'])){
unset($_SERVER);
} else {
$_SERVER = $GLOBALS['savedSERVER']['value'];
}
$GLOBALS['savedSERVER']['saved'] = false;
$GLOBALS['savedSERVER']['value'] = null;
}
}
}