<?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
* @package seek_quarry\tests
*/
namespace seekquarry\yioop\tests;
use seekquarry\yioop\configs as C;
use seekquarry\yioop\controllers\StaticController;
use seekquarry\yioop\library\UnitTest;
/**
* Checks how the static controller picks the group whose wiki pages it
* serves. A domain an admin routes to a landing group is served through
* this controller, and the router hands it that group's id on the
* ROUTE_GROUP_ID server variable; with no route, or a malformed one, the
* world-readable Public group must be served instead. These cases pin
* that resolution down so a stray or forged value cannot select an
* arbitrary group.
*
* @author Chris Pollett
*/
class StaticControllerTest extends UnitTest
{
/**
* The controller whose group resolver is under test.
* @var StaticController
*/
public $controller;
/**
* Builds a controller for each test case without running its
* constructor, since the group resolver only reads the request's
* server variables and needs none of the controller's normal set-up.
*/
public function setUp()
{
$reflection = new \ReflectionClass(StaticController::class);
$this->controller = $reflection->newInstanceWithoutConstructor();
}
/**
* Clears the routed-group server variable so one case does not leak
* into the next.
*/
public function tearDown()
{
unset($_SERVER['ROUTE_GROUP_ID']);
}
/**
* With no routed group set, the Public group is served, the
* historical behavior for the site's own static pages.
*/
public function defaultsToPublicGroupTestCase()
{
unset($_SERVER['ROUTE_GROUP_ID']);
$this->assertEqual($this->controller->staticGroupId(),
C\PUBLIC_GROUP_ID,
"no route serves the Public group");
}
/**
* A positive routed group id is served as an integer, so a domain
* pointed at a custom landing group reads that group's pages.
*/
public function usesPositiveRoutedGroupTestCase()
{
$_SERVER['ROUTE_GROUP_ID'] = "7";
$this->assertEqual($this->controller->staticGroupId(), 7,
"a positive route selects that group");
$this->assertTrue(
$this->controller->staticGroupId() === 7,
"the routed id comes back as an integer");
}
/**
* A zero or negative routed group id is treated as no route and
* falls back to the Public group.
*/
public function rejectsNonPositiveRoutedGroupTestCase()
{
$_SERVER['ROUTE_GROUP_ID'] = "0";
$this->assertEqual($this->controller->staticGroupId(),
C\PUBLIC_GROUP_ID,
"a zero route falls back to the Public group");
$_SERVER['ROUTE_GROUP_ID'] = "-5";
$this->assertEqual($this->controller->staticGroupId(),
C\PUBLIC_GROUP_ID,
"a negative route falls back to the Public group");
}
/**
* A non-numeric routed group id cannot select a group and falls back
* to the Public group.
*/
public function rejectsNonNumericRoutedGroupTestCase()
{
$_SERVER['ROUTE_GROUP_ID'] = "not_a_number";
$this->assertEqual($this->controller->staticGroupId(),
C\PUBLIC_GROUP_ID,
"a non-numeric route falls back to the Public group");
}
/**
* On a routed group a baked group-controller self link written with
* clean urls is rewritten to its static p/ url, keeping the page
* name.
*/
public function rewritesCleanUrlSelfLinkTestCase()
{
$_SERVER['ROUTE_GROUP_ID'] = "100";
$html = '<a href="http://localhost/[{controller}]/100?a=wiki' .
'&[{token}]&page_name=bob">BOB</a>';
$out = $this->controller->rewriteRoutedGroupLinks($html);
$this->assertTrue(
strpos($out, 'href="' . C\SHORT_BASE_URL . 'p/bob"') !== false,
"clean-url self link becomes the static p/ url");
$this->assertTrue(strpos($out, '[{token}]') === false,
"the token placeholder is gone from the rewritten link");
}
/**
* The rewrite keys on the page_name query the read url ends with, so
* a self link written as a query string, not clean urls, is rewritten
* the same way.
*/
public function rewritesQueryStringSelfLinkTestCase()
{
$_SERVER['ROUTE_GROUP_ID'] = "100";
$html = '<a href="/src/?c=[{controller}]&a=wiki&' .
'group_id=100&[{token}]&page_name=bob">BOB</a>';
$out = $this->controller->rewriteRoutedGroupLinks($html);
$this->assertTrue(
strpos($out, 'href="' . C\SHORT_BASE_URL . 'p/bob"') !== false,
"query-string self link becomes the static p/ url");
}
/**
* A page served for the Public group keeps its links untouched, since
* the Public group already carries controller-agnostic links.
*/
public function leavesPublicGroupLinksUnchangedTestCase()
{
unset($_SERVER['ROUTE_GROUP_ID']);
$html = '<a href="[{controller_and_page}]bob">BOB</a>';
$this->assertEqual(
$this->controller->rewriteRoutedGroupLinks($html), $html,
"a Public page's links are returned unchanged");
}
}