340 lines
13 KiB
PHP
340 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 testInit()
|
|
{
|
|
$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";
|
|
}
|
|
});
|
|
$this->assertTrue($displayErrors);
|
|
}
|
|
|
|
/**
|
|
* @depends testInit
|
|
* @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->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){
|
|
|
|
}
|
|
$cwd = getcwd();
|
|
$this->revertSERVER();
|
|
$this->assertTrue($thrown,"TestBaseUrlException not found");
|
|
$this->assertEquals($waitedBaseUrl,$foundTh->getBaseUrl(),"Not same baseUrl");
|
|
$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');
|
|
|
|
// echo "\n";
|
|
// foreach($data as $name => $line){
|
|
// echo "$name => ".implode(',',$line)."\n";
|
|
// }
|
|
return $data;
|
|
}
|
|
|
|
protected function prepareAPage(
|
|
array &$data,
|
|
string $baseScriptName,
|
|
string $rootFolder,
|
|
string $pageId
|
|
)
|
|
{
|
|
$baseUrl = 'http://localhost'.$baseScriptName.'/';
|
|
$isIndex = ($pageId == 'index');
|
|
$isSubIndex = (substr($pageId,-strlen('/index')) == '/index');
|
|
$pageIdInUrl = $isIndex ? '' : ($isSubIndex ? substr($pageId,0,-strlen('/index')) : $pageId) ;
|
|
$queriesStrings = $isIndex ? [['q'=>'','s'=>'','f'=>'']] : [
|
|
['q'=>$pageIdInUrl,'s'=>'','f'=>''],
|
|
['q'=>'','s'=>$pageIdInUrl,'f'=>''],
|
|
['q'=>'','s'=>$pageIdInUrl,'f'=>$pageIdInUrl],
|
|
['q'=>$pageIdInUrl,'s'=>$pageIdInUrl,'f'=>''],
|
|
['q'=>$pageIdInUrl,'s'=>$pageIdInUrl,'f'=>$pageIdInUrl]
|
|
];
|
|
foreach ($queriesStrings as $queryData) {
|
|
$queryString = empty($queryData['q']) ? '' :'?'.$queryData['q'];
|
|
$scriptNameMiddle = empty($queryData['s']) ? '' : $queryData['s'].'/';
|
|
foreach (['','index.php'] as $endScriptName) {
|
|
$formattedQueryString = str_replace('/','%2F',$queryString);
|
|
$pageUrl = empty($queryData['s']) ? (empty($queryData['q']) ? '' : $formattedQueryString) : $queryData['s'];
|
|
$canRewriteFromRoot = empty($queryData['s']) && empty($queryData['f']);
|
|
if ($rootFolder == 'content' && $canRewriteFromRoot){
|
|
$scriptName = "$baseScriptName/$scriptNameMiddle$endScriptName";
|
|
$name = $rootFolder.$scriptName.$queryString.'*';
|
|
$this->prepareData($data,$name,$rootFolder,'index.php',$scriptName,$queryData['q'],$baseUrl,$pageId,$pageUrl);
|
|
}
|
|
foreach ([false,true] as $withRewrite) {
|
|
if ($withRewrite){
|
|
$scriptName = "$baseScriptName/$scriptNameMiddle$endScriptName";
|
|
$name = $rootFolder.$scriptName.$queryString.' R';
|
|
$waitedUrl = $baseUrl;
|
|
} else {
|
|
$scriptName = "$baseScriptName/$rootFolder/$scriptNameMiddle$endScriptName";
|
|
$name = $rootFolder.$scriptName.$queryString;
|
|
$waitedUrl = $baseUrl.$rootFolder.'/';
|
|
}
|
|
if ($canRewriteFromRoot){
|
|
$this->prepareData($data,$name."*",$rootFolder,"index.php",$scriptName,$queryData['q'],$waitedUrl,$pageId,$pageUrl);
|
|
}
|
|
$formattedRootMiddle = empty($pageIdInUrl) ? '' : "/$pageIdInUrl";
|
|
$this->prepareData($data,$name,$rootFolder,"$rootFolder$formattedRootMiddle/index.php",$scriptName,$queryData['q'],$waitedUrl,$pageId,$pageUrl);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected function prepareData(
|
|
array &$data,
|
|
string $name,
|
|
string $rootFolder,
|
|
string $filePath,
|
|
string $shortScriptName,
|
|
string $queryString,
|
|
string $waitedBaseUrl,
|
|
string $waitedPageId,
|
|
string $waitedPageEndUrl
|
|
)
|
|
{
|
|
$waitedPageUrl = $waitedBaseUrl.$waitedPageEndUrl;
|
|
$nbLevels = in_array($shortScriptName,['/','/index.php']) ? 0 : count(explode('/',$rootFolder));
|
|
$prefix = implode('/',array_fill(0,$nbLevels,'..'));
|
|
if (!empty($prefix)){
|
|
$prefix .= '/';
|
|
}
|
|
$waitedThemesUrl = $waitedBaseUrl.$prefix.'vendor/picocms/themes';
|
|
$waitedPluginsUrl = $waitedBaseUrl.$prefix.'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_ADDR'] = '80'; // forced
|
|
$_SERVER['SERVER_NAME'] = 'localhost'; // forced
|
|
$_SERVER['HTTPS'] = null; // forced
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
}
|
|
} |