Compare commits

...

2 Commits

Author SHA1 Message Date
Jérémy Dufraisse
9868fc8c3d fix(AppTest): test more stable and rewrite URL decode 2023-12-25 17:18:23 +01:00
Jérémy Dufraisse
910596dae3 fix(composer): migrate to accolades 2023-12-25 17:17:49 +01:00
4 changed files with 309 additions and 1009 deletions

278
App.php
View File

@ -141,64 +141,244 @@ class App
*/ */
protected function update_SERVERIfNeeded(Pico $pico, string $configDir) protected function update_SERVERIfNeeded(Pico $pico, string $configDir)
{ {
$requestUrl = null; $data = [
$config = [ 'FROM_QUERY_STRING' => '',
'rewrite_url' => false, 'FROM_SCRIPT_NAME' => '',
'themes_url' => self::THEMES_PATH, 'FROM_SCRIPT_FILENAME' => '',
'plugins_url' => self::PLUGINS_PATH, 'rootPath' => '/',
'rootPathFound' => false,
'rewriteModeactivated' => false,
'page' => 'index',
'continue' => true
]; ];
$nbLevels = 0; $this
->extractRequestUrlFormQueryString($data)
->extractRequestUrlFromScriptFileName($data,$configDir)
->extractRequestUrlFromScriptName($data,$configDir)
->extractRootPathFromScriptNameIfNeeded($data,$configDir)
->definePage($data)
->setUrl($data, $configDir, $pico);
}
// use QUERY_STRING; e.g. /pico/?sub/page /**
$pathComponent = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : ''; * extract requestUrlFromQueryString
if ($pathComponent) { * @param array &$data
$pathComponent = strstr($pathComponent, '&', true) ?: $pathComponent; * @return self
if (strpos($pathComponent, '=') === false) { */
$requestUrl = trim(rawurldecode($pathComponent), '/'); protected function extractRequestUrlFormQueryString(array &$data): self
{
if ($data['continue']){
// use QUERY_STRING; e.g. ?sub/page
$qString = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '';
if ($qString) {
$qString = strstr($qString, '&', true) ?: $qString;
if (strpos($qString, '=') === false) {
$data['FROM_QUERY_STRING'] = $qString;
}
} }
} }
return $this;
}
if (isset($_SERVER)){ /**
if (!empty($requestUrl)){ * extract requestUrlFromScriptName
$supposedEndUrlForRewrite = $configDir.$requestUrl.'/index.php'; * @param array &$data
$supposedEndUrlForNotRewrite = $configDir.'index.php'; * @param string $configDir
if (!empty($_SERVER['SCRIPT_NAME']) && substr($_SERVER['SCRIPT_NAME'],-strlen($supposedEndUrlForRewrite)) == $supposedEndUrlForRewrite){ * @return self
$_SERVER['SCRIPT_NAME'] = str_replace($supposedEndUrlForRewrite,$configDir.'index.php',$_SERVER['SCRIPT_NAME']); */
if (!empty($_SERVER['SCRIPT_FILENAME'])){ protected function extractRequestUrlFromScriptName(array &$data, string $configDir): self
$_SERVER['SCRIPT_FILENAME'] = str_replace($supposedEndUrlForRewrite,$configDir.'index.php',$_SERVER['SCRIPT_FILENAME']); {
} if ($data['continue'] && !empty($_SERVER['SCRIPT_NAME']) && is_string($_SERVER['SCRIPT_NAME'])){
if (!empty($_SERVER['REQUEST_URI'])){ // use SCRIPT_NAME; e.g. /subfolder/content/sub/page/index.php
$_SERVER['REQUEST_URI'] = str_replace([$configDir.$requestUrl.'/',$configDir.$requestUrl],$configDir,$_SERVER['REQUEST_URI']); $matches = [];
} $configDirForMatch = preg_quote($configDir,'/');
$config['rewrite_url'] = true; if (preg_match("/^(.*)$configDirForMatch(.*)(?!.php)(?:index.php)?$/",$_SERVER['SCRIPT_NAME'],$matches)){
$nbLevels = count(explode('/',$configDir.$requestUrl)); $data['rootPath'] = $matches[1];
} elseif (!empty($_SERVER['SCRIPT_NAME']) && substr($_SERVER['SCRIPT_NAME'],-strlen($supposedEndUrlForNotRewrite)) == $supposedEndUrlForNotRewrite) { $data['rootPathFound'] = true;
$nbLevels = count(explode('/',$configDir)) -1; $data['FROM_SCRIPT_NAME'] = $this->formatStringWithLeadingSlash($matches[2],false);
} } elseif (!empty($data['FROM_SCRIPT_FILENAME']) && (
} elseif (!empty($_SERVER['SCRIPT_NAME']) && is_string($_SERVER['SCRIPT_NAME'])) { $this->isServerEndedBy("{$data['FROM_SCRIPT_FILENAME']}/index.php",'SCRIPT_NAME') ||
$this->isServerEndedBy("{$data['FROM_SCRIPT_FILENAME']}/",'SCRIPT_NAME')
)
){
$data['rootPath'] = $this->formatStringWithLeadingSlash($matches[2],false);
$data['rootPathFound'] = true;
$data['FROM_SCRIPT_NAME'] = $data['FROM_SCRIPT_FILENAME'];
$data['rewriteModeactivated'] = true;
}
}
return $this;
}
/**
* extract requestUrlFromScriptFileName
* @param array &$data
* @param string $configDir
* @return self
*/
protected function extractRequestUrlFromScriptFileName(array &$data, string $configDir): self
{
if ($data['continue'] &&
!empty($_SERVER['SCRIPT_FILENAME']) &&
is_string($_SERVER['SCRIPT_FILENAME']) &&
substr($_SERVER['SCRIPT_FILENAME'],-strlen('index.php')) == 'index.php'){
// use SCRIPT_FILENAME; e.g. /var/www/subfolder/content/sub/page/index.php
// check if the current folder seems to correspond to root folder of seacms
if (is_dir('content') && is_dir('sites') && is_file('index.php')){
$cwd = realpath(getcwd());
$truncatedFileName = substr(realpath($_SERVER['SCRIPT_FILENAME']),strlen($cwd));
$matches = []; $matches = [];
$configDirForMatch = preg_quote($configDir,'/'); $configDirForMatch1 = preg_quote($configDir,'/');
if (preg_match("/^(.*)$configDirForMatch(.*)index.php$/",$_SERVER['SCRIPT_NAME'],$matches)){ $configDirForMatch2 = preg_quote(str_replace('/','\\',$configDir),'/');
$rootPath = $matches[1]; if (preg_match("/^(.*)(?:$configDirForMatch1|$configDirForMatch2)(.*)index.php$/",$_SERVER['SCRIPT_FILENAME'],$matches)){
$requestUrl = !empty($matches[2]) ? (substr($matches[2],-1) == '/' ? substr($matches[2],0,-1) : $matches[2]) : ''; $formFileName = str_replace('\\','/',$matches[2]);
$data['FROM_SCRIPT_FILENAME'] = $this->formatStringWithLeadingSlash($formFileName,false);
if (!empty($requestUrl)){
$supposedEndUrlForRewrite = $configDir.$requestUrl.'/index.php';
if (!empty($_SERVER['SCRIPT_FILENAME'])){
$_SERVER['SCRIPT_FILENAME'] = str_replace($supposedEndUrlForRewrite,$configDir.'index.php',$_SERVER['SCRIPT_FILENAME']);
}
if (!empty($_SERVER['SCRIPT_NAME'])){
$_SERVER['SCRIPT_NAME'] = str_replace($supposedEndUrlForRewrite,$configDir.'index.php',$_SERVER['SCRIPT_NAME']);
}
}
$nbLevels = count(explode('/',$configDir)) -1;
$config['rewrite_url'] = true;
} }
} }
} }
$previous = implode('',array_fill(0,$nbLevels,'../')); return $this;
$config['themes_url'] = $previous.$config['themes_url']; }
$config['plugins_url'] = $previous.$config['plugins_url'];
/**
* extract rootPath from ScriptName
* @param array &$data
* @param string $configDir
* @return self
*/
protected function extractRootPathFromScriptNameIfNeeded(array &$data, string $configDir): self
{
if ($data['continue'] && !$data['rootPathFound']){
// use SCRIPT_NAME; e.g. /subfolder/index.php
$matches = [];
$wantedPage = empty($data['FROM_SCRIPT_FILENAME']) ? '' : $data['FROM_SCRIPT_FILENAME'];
$wantedPageQuoted = preg_quote($wantedPage,'/');
if (preg_match("/^(.*){$wantedPageQuoted}\/(?:index.php)?$/",$_SERVER['SCRIPT_NAME'],$matches)){
$data['rootPath'] = $this->formatStringWithLeadingSlash($matches[1],true);
$data['rootPathFound'] = true;
$data['rewriteModeactivated'] = (realpath($_SERVER['SCRIPT_FILENAME']) == realpath(getcwd()."/{$configDir}index.php"));
}
}
return $this;
}
/**
* format string with leading '/'
* @param null|string $rawString
* @param bool $withLeadingSlash
* @return string $page
*/
protected function formatStringWithLeadingSlash(?string $rawString, bool $withLeadingSlash = false): string
{
return $withLeadingSlash
? (!empty($rawString) ? (substr($rawString,-1) == '/' ? $rawString : $rawString.'/') : '/')
: (!empty($rawString) ? (substr($rawString,-1) == '/' ? substr($rawString,0,-1) : $rawString) : '');
}
/**
* define page
* @param array $data
* @return $this
*/
protected function definePage(array &$data): self
{
if ($data['continue']){
$data['page'] = !empty($data['FROM_QUERY_STRING'])
? $data['FROM_QUERY_STRING']
: (
!empty($data['FROM_SCRIPT_NAME'])
? $data['FROM_SCRIPT_NAME']
: (
!empty($data['FROM_SCRIPT_FILENAME'])
? $data['FROM_SCRIPT_FILENAME']
: 'index'
)
);
}
return $this;
}
/**
* set SERVER QUERY_STRING
* @param array $data
* @param string $configDir
* @param Pico $pico
* @return $this
*/
protected function setUrl(array $data, string $configDir, Pico $pico): self
{
$bfserver = $_SERVER;
// SCRIPT_NAME
$rootPath = (empty($data['rootPath']) || !is_string($data['rootPath'])) ? '/' : $this->formatStringWithLeadingSlash($data['rootPath'],true);
$_SERVER['SCRIPT_NAME'] = $rootPath.($data['rewriteModeactivated']?'':$configDir).'index.php';
$_SERVER['PHP_SELF'] = $_SERVER['SCRIPT_NAME'].($_SERVER['PATH_INFO'] ?? '');
$_SERVER['DOCUMENT_URI'] = $_SERVER['PHP_SELF'];
// QUERY_STRING
$qString = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '';
if (substr($qString,0,strlen($data['page'])+1)==$data['page'].'&'){
$qString = substr($qString,strlen($data['page'])+1);
} elseif ($qString == $data['page']){
$qString = '';
}
if (!empty($data['page'])){
$qString = $data['page'].(empty($qString) ? '' : "&$qString");
}
$_SERVER['QUERY_STRING'] = $qString;
$_SERVER['REQUEST_URI'] = $_SERVER['DOCUMENT_URI'].(empty($_SERVER['QUERY_STRING'])?'':"?{$_SERVER['QUERY_STRING']}");
//SCRIPT_FILENAME
$cwd = getcwd();
$fn = str_replace('\\','/',realpath($cwd.'/'.$configDir.'index.php'));
$_SERVER['SCRIPT_FILENAME'] = $fn;
// config
$baseUrl = $this->getBaseUrl($rootPath,$configDir,$pico);
$config = $pico->getConfig();
$config['rewrite_url'] = true;
$config['configDir'] = $this->formatStringWithLeadingSlash($configDir,false);
$config['content_dir'] = $this->formatStringWithLeadingSlash($configDir,false);
$config['themes_url'] = "$baseUrl$rootPath".self::THEMES_PATH;
$config['plugins_url'] = "$baseUrl$rootPath".self::PLUGINS_PATH;
$pico->setConfig($config); $pico->setConfig($config);
$server = $_SERVER;
$dataJSON = json_encode(compact(['data','configDir','qString','cwd','fn','config','server','bfserver']));
// echo <<<HTML
// <script>
// console.log($dataJSON)
// </script>
// HTML;
return $this;
}
/**
* test if $_SERVER[$key] end by $wantedValue
* @param string $wantedValue
* @param string $key
* @return bool
*/
protected function isServerEndedBy(string $wantedValue, string $key): bool
{
return (!empty($_SERVER[$key]) && is_string($_SERVER[$key]) && substr($_SERVER[$key],-strlen($wantedValue)) == $wantedValue);
}
/**
* generate Base Url
* @param string $rootPath
* @param string $configDir
* @param Pico $pico
* @return string
*/
protected function getBaseUrl(string $rootPath,string $configDir, Pico $pico): string
{
$baseUrl = $this->formatStringWithLeadingSlash($pico->getBaseUrl(),true);
if (substr($baseUrl,-strlen($rootPath.$configDir)) == $rootPath.$configDir){
$baseUrl = substr($baseUrl,0,-strlen($rootPath.$configDir));
}
return $this->formatStringWithLeadingSlash($baseUrl,false);
} }
} }

View File

@ -12,7 +12,7 @@
"ext-mbstring": "*", "ext-mbstring": "*",
"ext-pcre": "*", "ext-pcre": "*",
"picocms/composer-installer": "dev-pico-3.0", "picocms/composer-installer": "dev-pico-3.0",
"picocms/pico": "dev-fix-compatibility-php8 as v3.0.0-alpha.2", "picocms/pico": "dev-pico-3.0",
"seacms/composer-plugin": "dev-master", "seacms/composer-plugin": "dev-master",
"seacms/seacms-api": "dev-master", "seacms/seacms-api": "dev-master",
"seacms/seacms-auth": "dev-master" "seacms/seacms-auth": "dev-master"
@ -58,19 +58,15 @@
"repositories": [ "repositories": [
{ {
"type": "vcs", "type": "vcs",
"url": "https://git.defis.info/SeaCMS/pico" "url": "https://git.accolades.coop/SeaCMS/seacms-api"
}, },
{ {
"type": "vcs", "type": "vcs",
"url": "https://git.defis.info/SeaCMS/seacms-api" "url": "https://git.accolades.coop/SeaCMS/seacms-auth"
}, },
{ {
"type": "vcs", "type": "vcs",
"url": "https://git.defis.info/SeaCMS/seacms-auth" "url": "https://git.accolades.coop/SeaCMS/composer-plugin"
},
{
"type": "vcs",
"url": "https://git.defis.info/SeaCMS/composer-plugin"
} }
] ]
} }

882
composer.lock generated
View File

@ -1,882 +0,0 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "8c6acb90dd7429741534e63b22acbbf9",
"packages": [
{
"name": "erusev/parsedown",
"version": "v2.0.0-beta-1",
"source": {
"type": "git",
"url": "https://github.com/erusev/parsedown.git",
"reference": "32278afaf36c758de026b66661d3afd6dfbea743"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/erusev/parsedown/zipball/32278afaf36c758de026b66661d3afd6dfbea743",
"reference": "32278afaf36c758de026b66661d3afd6dfbea743",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"php": "^7.1||^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.0.0",
"infection/infection": "^0.25.0",
"phpunit/phpunit": "^9.3.11||^8.5.21||^7.5.20",
"roave/infection-static-analysis-plugin": "^1.10.0",
"vimeo/psalm": "^4.10.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Erusev\\Parsedown\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Emanuil Rusev",
"email": "hello@erusev.com",
"homepage": "http://erusev.com"
}
],
"description": "Parser for Markdown.",
"homepage": "http://parsedown.org",
"keywords": [
"markdown",
"parser"
],
"support": {
"issues": "https://github.com/erusev/parsedown/issues",
"source": "https://github.com/erusev/parsedown/tree/v2.0.0-beta-1"
},
"time": "2022-05-21T21:40:24+00:00"
},
{
"name": "erusev/parsedown-extra",
"version": "v2.0.0-beta-1",
"source": {
"type": "git",
"url": "https://github.com/erusev/parsedown-extra.git",
"reference": "aaed6a888230a9ffb5ef35e9f403ba2b5e4e21ef"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/erusev/parsedown-extra/zipball/aaed6a888230a9ffb5ef35e9f403ba2b5e4e21ef",
"reference": "aaed6a888230a9ffb5ef35e9f403ba2b5e4e21ef",
"shasum": ""
},
"require": {
"erusev/parsedown": "^2.0.0|^2.0.0-beta-1",
"ext-mbstring": "*",
"php": "^7.1||^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.0.0",
"infection/infection": "^0.25.0",
"phpunit/phpunit": "^9.3.11||^8.5.21||^7.5.20",
"roave/infection-static-analysis-plugin": "^1.10.0",
"vimeo/psalm": "^4.10.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Erusev\\ParsedownExtra\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Emanuil Rusev",
"email": "hello@erusev.com",
"homepage": "http://erusev.com"
}
],
"description": "An extension of Parsedown that adds support for Markdown Extra.",
"homepage": "https://github.com/erusev/parsedown-extra",
"keywords": [
"markdown",
"markdown extra",
"parsedown",
"parser"
],
"support": {
"issues": "https://github.com/erusev/parsedown-extra/issues",
"source": "https://github.com/erusev/parsedown-extra/tree/v2.0.0-beta-1"
},
"time": "2022-05-21T21:46:56+00:00"
},
{
"name": "picocms/composer-installer",
"version": "dev-pico-3.0",
"source": {
"type": "git",
"url": "https://github.com/picocms/composer-installer.git",
"reference": "8e59c0f0ab55af384b4a788179de4e169bb1f60e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/picocms/composer-installer/zipball/8e59c0f0ab55af384b4a788179de4e169bb1f60e",
"reference": "8e59c0f0ab55af384b4a788179de4e169bb1f60e",
"shasum": ""
},
"require": {
"composer-plugin-api": "^2.1",
"php": ">=7.2"
},
"type": "composer-plugin",
"extra": {
"class": "picocms\\ComposerInstaller\\Plugin",
"branch-alias": {
"dev-master": "1.0.x-dev",
"dev-pico-3.0": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"picocms\\ComposerInstaller\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Daniel Rudolf",
"email": "picocms.org@daniel-rudolf.de",
"role": "Lead Developer"
},
{
"name": "The Pico Community",
"homepage": "https://picocms.org/"
},
{
"name": "Contributors",
"homepage": "https://github.com/picocms/composer-installer/graphs/contributors"
}
],
"description": "A composer plugin responsible for installing plugins and themes for Pico, a stupidly simple, blazing fast, flat file CMS.",
"homepage": "https://picocms.org/",
"keywords": [
"composer",
"composer-installer",
"composer-plugin",
"pico",
"pico-cms",
"picocms",
"picocms-installer",
"picocms-plugin",
"picocms-theme"
],
"support": {
"issues": "https://github.com/picocms/composer-installer/issues",
"source": "https://github.com/picocms/composer-installer"
},
"time": "2022-02-27T16:50:04+00:00"
},
{
"name": "picocms/pico",
"version": "dev-fix-compatibility-php8",
"source": {
"type": "git",
"url": "https://git.defis.info/SeaCMS/pico",
"reference": "4342526f6d60fe72c87f7c2fd02c0b9bf4513db5"
},
"require": {
"erusev/parsedown": "^2.0.0-beta-1",
"erusev/parsedown-extra": "^2.0.0-beta-1",
"ext-mbstring": "*",
"php": "^7.0.8 || ^8.0",
"symfony/yaml": "^3.4",
"twig/twig": "^2.12"
},
"suggest": {
"picocms/composer-installer": "This Composer plugin is responsible for installing Pico plugins and themes using the Composer package manager.",
"picocms/pico-deprecated": "PicoDeprecated's purpose is to maintain backward compatibility to older versions of Pico.",
"picocms/pico-theme": "Pico requires a theme to actually display the contents of your website. This is Pico's official default theme."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.1.x-dev",
"dev-pico-3.0": "3.0.x-dev"
}
},
"autoload": {
"psr-0": {
"Pico": "lib/",
"PicoPluginInterface": "lib/",
"AbstractPicoPlugin": "lib/"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Gilbert Pellegrom",
"email": "gilbert@pellegrom.me",
"role": "Project Founder"
},
{
"name": "Daniel Rudolf",
"email": "picocms.org@daniel-rudolf.de",
"role": "Lead Developer"
},
{
"name": "The Pico Community",
"homepage": "http://picocms.org/"
},
{
"name": "Contributors",
"homepage": "https://github.com/picocms/Pico/graphs/contributors"
}
],
"description": "Pico is a flat file CMS, this means there is no administration backend and database to deal with. You simply create .md files in the \"content\" folder and that becomes a page.",
"homepage": "http://picocms.org/",
"keywords": [
"cms",
"content-management",
"flat-file",
"markdown",
"markdown-to-html",
"php",
"pico",
"pico-cms",
"picocms",
"simple",
"twig",
"website",
"yaml"
],
"support": {
"docs": "http://picocms.org/docs",
"issues": "https://github.com/picocms/Pico/issues",
"source": "https://github.com/picocms/Pico"
},
"time": "2023-03-21T07:53:30+00:00"
},
{
"name": "seacms/composer-plugin",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://git.defis.info/SeaCMS/composer-plugin",
"reference": "adc22cdee66306b9392435bf5407cf455b508608"
},
"require": {
"composer-plugin-api": "^2.3",
"picocms/pico": "*",
"topfloor/composer-cleanup-vcs-dirs": "^1.1"
},
"replace": {
"symfony/finder": "*"
},
"require-dev": {
"phpunit/phpunit": "^8.5"
},
"default-branch": true,
"type": "composer-plugin",
"extra": {
"class": "Seacms\\ComposerInstaller\\Plugin",
"plugin-modifies-downloads": true
},
"autoload": {
"psr-4": {
"Seacms\\ComposerInstaller\\": "src/installer/",
"Seacms\\Command\\": "src/commands/"
}
},
"license": [
"EUPL-1.2"
],
"authors": [
{
"name": "Jérémy Dufraisse",
"homepage": "https://github.com/J9rem",
"role": "SeaCMS developer"
}
],
"description": "Composer plugin SeaCMS",
"homepage": "https://git.defis.info/SeaCMS/composer-plugin",
"keywords": [
"composer-plugin",
"seacma"
],
"support": {
"docs": "https://git.defis.info/SeaCMS/composer-plugin/src/branch/master/README.md",
"issues": "https://git.defis.info/SeaCMS/composer-plugin/issues",
"source": "https://git.defis.info/SeaCMS/composer-plugin"
},
"time": "2023-03-23T10:42:37+00:00"
},
{
"name": "seacms/seacms-api",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://git.defis.info/SeaCMS/seacms-api",
"reference": "f3574dd6d68d1ef31fa3534c4d9b96aac4ef2bc1"
},
"require": {
"php": "^7.2.5||^8.0"
},
"default-branch": true,
"type": "pico-plugin",
"autoload": {
"psr-4": {
"SeaCMS\\Api\\": "src"
},
"classmap": [
"SeacmsApi.php"
]
},
"license": [
"EUPL-1.2"
],
"authors": [
{
"name": "Jérémy Dufraisse",
"homepage": "https://github.com/J9rem",
"role": "SeaCMS developer"
}
],
"description": "API route for SeaCMS",
"homepage": "https://git.defis.info/SeaCMS/seacms-api",
"keywords": [
"api",
"pico",
"picocms",
"picocms-plugin"
],
"support": {
"docs": "https://git.defis.info/SeaCMS/seacms-api/src/branch/master/README.md",
"issues": "https://git.defis.info/SeaCMS/seacms-api/issues",
"source": "https://git.defis.info/SeaCMS/seacms-api"
},
"time": "2023-03-23T10:38:49+00:00"
},
{
"name": "seacms/seacms-auth",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://git.defis.info/SeaCMS/seacms-auth",
"reference": "1955005a69850591e5f95732f6ddfa00a88e77dc"
},
"require": {
"php": "^7.2.5||^8.0",
"seacms/seacms-api": "dev-master"
},
"default-branch": true,
"type": "pico-plugin",
"autoload": {
"classmap": [
"SeacmsAuth.php"
]
},
"license": [
"EUPL-1.2"
],
"authors": [
{
"name": "Jérémy Dufraisse",
"homepage": "https://github.com/J9rem",
"role": "SeaCMS developer"
}
],
"description": "API route for SeaCMS",
"homepage": "https://git.defis.info/SeaCMS/seacms-auth",
"keywords": [
"auth",
"pico",
"picocms",
"picocms-plugin"
],
"support": {
"docs": "https://git.defis.info/SeaCMS/seacms-auth/src/branch/master/README.md",
"issues": "https://git.defis.info/SeaCMS/seacms-auth/issues",
"source": "https://git.defis.info/SeaCMS/seacms-auth"
},
"time": "2023-03-23T10:39:38+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-ctype": "*"
},
"suggest": {
"ext-ctype": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"ctype",
"polyfill",
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-mbstring": "*"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97",
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php72\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/yaml",
"version": "v3.4.47",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "88289caa3c166321883f67fe5130188ebbb47094"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/88289caa3c166321883f67fe5130188ebbb47094",
"reference": "88289caa3c166321883f67fe5130188ebbb47094",
"shasum": ""
},
"require": {
"php": "^5.5.9|>=7.0.8",
"symfony/polyfill-ctype": "~1.8"
},
"conflict": {
"symfony/console": "<3.4"
},
"require-dev": {
"symfony/console": "~3.4|~4.0"
},
"suggest": {
"symfony/console": "For validating YAML files using the lint command"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Yaml\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/yaml/tree/v3.4.47"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-10-24T10:57:07+00:00"
},
{
"name": "topfloor/composer-cleanup-vcs-dirs",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/VolantisDev/composer-cleanup-vcs-dirs.git",
"reference": "dfa7c8c0fe22e048310d00f133f7df14f0b2f57a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/VolantisDev/composer-cleanup-vcs-dirs/zipball/dfa7c8c0fe22e048310d00f133f7df14f0b2f57a",
"reference": "dfa7c8c0fe22e048310d00f133f7df14f0b2f57a",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1 | ^2",
"php": ">=5.5",
"symfony/finder": "*"
},
"require-dev": {
"composer/composer": "dev-master"
},
"type": "composer-plugin",
"extra": {
"class": "TopFloor\\ComposerCleanupVcsDirs\\Plugin"
},
"autoload": {
"psr-4": {
"TopFloor\\ComposerCleanupVcsDirs\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"GPL-2.0+"
],
"description": "Automatically deletes .git directories in newly installed or updated dependencies.",
"support": {
"issues": "https://github.com/VolantisDev/composer-cleanup-vcs-dirs/issues",
"source": "https://github.com/VolantisDev/composer-cleanup-vcs-dirs/tree/1.1.0"
},
"time": "2021-07-09T16:11:23+00:00"
},
{
"name": "twig/twig",
"version": "v2.15.4",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "3e059001d6d597dd50ea7c74dd2464b4adea48d3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/3e059001d6d597dd50ea7c74dd2464b4adea48d3",
"reference": "3e059001d6d597dd50ea7c74dd2464b4adea48d3",
"shasum": ""
},
"require": {
"php": ">=7.1.3",
"symfony/polyfill-ctype": "^1.8",
"symfony/polyfill-mbstring": "^1.3",
"symfony/polyfill-php72": "^1.8"
},
"require-dev": {
"psr/container": "^1.0",
"symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.15-dev"
}
},
"autoload": {
"psr-0": {
"Twig_": "lib/"
},
"psr-4": {
"Twig\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
},
{
"name": "Twig Team",
"role": "Contributors"
},
{
"name": "Armin Ronacher",
"email": "armin.ronacher@active-4.com",
"role": "Project Founder"
}
],
"description": "Twig, the flexible, fast, and secure template language for PHP",
"homepage": "https://twig.symfony.com",
"keywords": [
"templating"
],
"support": {
"issues": "https://github.com/twigphp/Twig/issues",
"source": "https://github.com/twigphp/Twig/tree/v2.15.4"
},
"funding": [
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/twig/twig",
"type": "tidelift"
}
],
"time": "2022-12-27T12:26:20+00:00"
}
],
"packages-dev": [],
"aliases": [
{
"package": "picocms/pico",
"version": "dev-fix-compatibility-php8",
"alias": "v3.0.0-alpha.2",
"alias_normalized": "3.0.0.0-alpha2"
}
],
"minimum-stability": "dev",
"stability-flags": {
"picocms/composer-installer": 20,
"picocms/pico": 20,
"seacms/composer-plugin": 20,
"seacms/seacms-api": 20,
"seacms/seacms-auth": 20
},
"prefer-stable": true,
"prefer-lowest": false,
"platform": {
"php": "^7.2.5||^8.0",
"ext-dom": "*",
"ext-filter": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-pcre": "*"
},
"platform-dev": [],
"platform-overrides": {
"php": "7.2.5"
},
"plugin-api-version": "2.3.0"
}

View File

@ -18,31 +18,32 @@ final class AppTest extends TestCase {
/** /**
* register error handlers * register error handlers
*/ */
public function testInit() public function registerErrorHandler()
{ {
$displayErrors = true; if (empty($GLOBALS['errrHandlerSet'])){
set_error_handler(function( $GLOBALS['errrHandlerSet'] = "1";
int $errno, $displayErrors = true;
string $errstr, set_error_handler(function(
?string $errfile = null, int $errno,
?int $errline = null, string $errstr,
?array $errcontext = null ?string $errfile = null,
) use (&$displayErrors){ ?int $errline = null,
if ($displayErrors){ ?array $errcontext = null
echo "\nError $errstr ($errno)\nIn file $errfile\nLine : $errline\n"; ) 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)){ register_shutdown_function(function (){
echo "\nAn error occured\n".json_encode($lastErr)."\n"; $lastErr = error_get_last();
} if (!is_null($lastErr)){
}); echo "\nAn error occured\n".json_encode($lastErr)."\n";
$this->assertTrue($displayErrors); }
});
}
} }
/** /**
* @depends testInit
* @dataProvider apiRewriteProvider * @dataProvider apiRewriteProvider
* @covers App::update_SERVERIfNeeded * @covers App::update_SERVERIfNeeded
* @param string $rootFolder * @param string $rootFolder
@ -67,6 +68,7 @@ final class AppTest extends TestCase {
string $waitedPluginsUrl, string $waitedPluginsUrl,
): void ): void
{ {
$this->registerErrorHandler();
$this->saveSERVER(); $this->saveSERVER();
$this->defineServer( $this->defineServer(
true, true,
@ -85,10 +87,11 @@ final class AppTest extends TestCase {
} catch (Throwable $th){ } catch (Throwable $th){
} }
$sn = $_SERVER['SCRIPT_NAME'];
$cwd = getcwd(); $cwd = getcwd();
$this->revertSERVER(); $this->revertSERVER();
$this->assertTrue($thrown,"TestBaseUrlException not found"); $this->assertTrue($thrown,"TestBaseUrlException not found");
$this->assertEquals($waitedBaseUrl,$foundTh->getBaseUrl(),"Not same baseUrl"); $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/plugins/",$foundTh->getPluginDir(),"Not same pluginDir");
$this->assertEquals("$cwd/vendor/picocms/themes/",$foundTh->getThemeDir(),"Not same themeDir"); $this->assertEquals("$cwd/vendor/picocms/themes/",$foundTh->getThemeDir(),"Not same themeDir");
$this->assertEquals("$cwd/",$foundTh->getRootDir(),"Not same rootDir"); $this->assertEquals("$cwd/",$foundTh->getRootDir(),"Not same rootDir");
@ -126,10 +129,6 @@ final class AppTest extends TestCase {
$this->prepareAPage($data,'/sea','sites/default','sub/index'); $this->prepareAPage($data,'/sea','sites/default','sub/index');
$this->prepareAPage($data,'/sea','sites/default','theme'); $this->prepareAPage($data,'/sea','sites/default','theme');
// echo "\n";
// foreach($data as $name => $line){
// echo "$name => ".implode(',',$line)."\n";
// }
return $data; return $data;
} }
@ -137,53 +136,64 @@ final class AppTest extends TestCase {
array &$data, array &$data,
string $baseScriptName, string $baseScriptName,
string $rootFolder, string $rootFolder,
string $pageId string $waitedPageId
) )
{ {
$baseUrl = 'http://localhost'.$baseScriptName.'/'; $baseUrl = 'http://localhost'.$baseScriptName.'/';
$isIndex = ($pageId == 'index');
$isSubIndex = (substr($pageId,-strlen('/index')) == '/index'); // tests
$pageIdInUrl = $isIndex ? '' : ($isSubIndex ? substr($pageId,0,-strlen('/index')) : $pageId) ; $isIndex = ($waitedPageId == 'index');
$queriesStrings = $isIndex ? [['q'=>'','s'=>'','f'=>'']] : [ $isSubIndex = (substr($waitedPageId,-strlen('/index')) == '/index');
['q'=>$pageIdInUrl,'s'=>'','f'=>''],
['q'=>'','s'=>$pageIdInUrl,'f'=>''], // intermediate variables
['q'=>'','s'=>$pageIdInUrl,'f'=>$pageIdInUrl], $pageIdInUrl = $isIndex ? '' : ($isSubIndex ? substr($waitedPageId,0,-strlen('/index')) : $waitedPageId) ;
['q'=>$pageIdInUrl,'s'=>$pageIdInUrl,'f'=>''], $waitedPageEndUrl = $pageIdInUrl;
['q'=>$pageIdInUrl,'s'=>$pageIdInUrl,'f'=>$pageIdInUrl]
]; foreach([false,true] as $viaQueryString){
foreach ($queriesStrings as $queryData) { $queryString = $viaQueryString ? $pageIdInUrl : '';
$queryString = empty($queryData['q']) ? '' :'?'.$queryData['q']; $queryStringWithQuestion = ($viaQueryString && !empty($pageIdInUrl)) ? "?$pageIdInUrl" : '';
$scriptNameMiddle = empty($queryData['s']) ? '' : $queryData['s'].'/'; $formattedQueryString = str_replace('/','%2F',$pageIdInUrl);
foreach (['','index.php'] as $endScriptName) {
$formattedQueryString = str_replace('/','%2F',$queryString); foreach (['','index.php'] as $endShortScriptName) {
$pageUrl = empty($queryData['s']) ? (empty($queryData['q']) ? '' : $formattedQueryString) : $queryData['s'];
$canRewriteFromRoot = empty($queryData['s']) && empty($queryData['f']); // $filePath from getcwd
if ($rootFolder == 'content' && $canRewriteFromRoot){
$scriptName = "$baseScriptName/$scriptNameMiddle$endScriptName"; if ($rootFolder == 'content' && $viaQueryString){
$name = $rootFolder.$scriptName.$queryString.'*'; // test also from base
$this->prepareData($data,$name,$rootFolder,'index.php',$scriptName,$queryData['q'],$baseUrl,$pageId,$pageUrl); $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 $withRewrite) {
if ($withRewrite){ foreach([false,true] as $viaScriptName){
$scriptName = "$baseScriptName/$scriptNameMiddle$endScriptName"; $folderInScriptName = ($viaScriptName && !empty($pageIdInUrl)) ? "$pageIdInUrl/" : '';
$name = $rootFolder.$scriptName.$queryString.' R'; $folderInScriptFileName = ($viaScriptName && !empty($pageIdInUrl)) ? "/$pageIdInUrl" :'' ;
$waitedUrl = $baseUrl;
} else { foreach ([false,true] as $withRewrite) {
$scriptName = "$baseScriptName/$rootFolder/$scriptNameMiddle$endScriptName"; if ($viaQueryString || $endShortScriptName){
$name = $rootFolder.$scriptName.$queryString; $filePath = "$rootFolder$folderInScriptFileName/index.php";
$waitedUrl = $baseUrl.$rootFolder.'/'; $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);
}
} }
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( protected function prepareData(
string $baseUrl,
array &$data, array &$data,
string $name, string $name,
string $rootFolder, string $rootFolder,
@ -196,13 +206,8 @@ final class AppTest extends TestCase {
) )
{ {
$waitedPageUrl = $waitedBaseUrl.$waitedPageEndUrl; $waitedPageUrl = $waitedBaseUrl.$waitedPageEndUrl;
$nbLevels = in_array($shortScriptName,['/','/index.php']) ? 0 : count(explode('/',$rootFolder)); $waitedThemesUrl = $baseUrl.'vendor/picocms/themes';
$prefix = implode('/',array_fill(0,$nbLevels,'..')); $waitedPluginsUrl = $baseUrl.'vendor/picocms/plugins';
if (!empty($prefix)){
$prefix .= '/';
}
$waitedThemesUrl = $waitedBaseUrl.$prefix.'vendor/picocms/themes';
$waitedPluginsUrl = $waitedBaseUrl.$prefix.'vendor/picocms/plugins';
$data[$name] = compact([ $data[$name] = compact([
'rootFolder', 'rootFolder',
'filePath', 'filePath',
@ -294,9 +299,10 @@ final class AppTest extends TestCase {
$_SERVER['REMOTE_ADDR'] = '127.0.0.1'; // forced $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; // forced
$_SERVER['REMOTE_PORT'] = '80'; // forced $_SERVER['REMOTE_PORT'] = '80'; // forced
$_SERVER['SERVER_ADDR'] = '127.0.0.1'; // forced $_SERVER['SERVER_ADDR'] = '127.0.0.1'; // forced
$_SERVER['SERVER_ADDR'] = '80'; // forced $_SERVER['SERVER_PORT'] = '80'; // forced
$_SERVER['SERVER_NAME'] = 'localhost'; // forced $_SERVER['SERVER_NAME'] = 'localhost'; // forced
$_SERVER['HTTPS'] = null; // forced $_SERVER['HTTPS'] = null; // forced
$_SERVER['REQUEST_TIME'] = time();
} }
} }