Typesetter-Original-gtbu/include/special/Missing.php

305 lines
7.1 KiB
PHP
Raw Normal View History

2021-09-08 19:52:21 +02:00
<?php
namespace gp\special;
defined('is_running') or die('Not an entry point...');
class Missing extends \gp\special\Base{
public $datafile;
public $error_data = array();
public $requested;
public function Init(){
$this->datafile = '_site/error_data';
$this->error_data = \gp\tool\Files::Get($this->datafile,'error_data');
$this->error_data += array(
'redirects' => array(
)
);
}
public function __construct($args){
global $langmessage;
parent::__construct($args);
$this->Init();
$this->requested = $this->page->requested;
}
public function RunScript(){
$cmd = \gp\tool::GetCommand();
$this->RunCommands($cmd);
}
public function DefaultDisplay(){
if( $this->page->gp_index !== 'special_missing' ){
$this->CheckRedirect();
$this->CheckSimilar();
}
$this->Get404();
}
/**
* Redirect the request if a redirection entry matches the requested page
*
*/
public function CheckRedirect(){
if( is_null($this->requested) ){
return;
}
$parts = explode('/',$this->requested);
$first_part = array_shift($parts);
if( !isset($this->error_data['redirects'][$first_part]) ){
return;
}
$target = $this->error_data['redirects'][$first_part]['target'];
$target = $this->GetTarget($target);
if( $target === false ){
return;
}
if( !empty($parts) && is_string($target) ){
$target .= '/'.implode('/',$parts);
}
$code = $this->error_data['redirects'][$first_part]['code'];
\gp\tool::Redirect($target,$code);
}
/**
* Redirect the request if the requested page closely matches an existing page
* If it's just a difference of case, then the similarity will be 100%
*
*/
public function CheckSimilar(){
global $config;
$requested = trim($this->requested,'/');
$similar = $this->SimilarTitleArray($requested);
$first_title = key($similar);
$first_percent = current($similar);
if( $config['auto_redir'] > 0 && $first_percent >= $config['auto_redir'] ){
$redirect = \gp\tool::GetUrl($first_title,http_build_query($_GET),false);
\gp\tool::Redirect($redirect);
}
}
/**
* Translate the $target url to a url that can be used with Header() or in a link
*
* @param string $target The user supplied value for redirection
* @param boolean $get_final If true, GetTarget() will check for additional redirection and $target existence before returning the url. Maximum of 10 redirects.
* @return string|false
*/
public function GetTarget($target,$get_final = true){
global $gp_index;
static $redirects = 0;
if( empty($target) ){
return \gp\tool::GetUrl('');
}
if( !$this->isGPLink($target) ){
return $target;
}
if( !$get_final ){
return \gp\tool::GetUrl($target);
}
//check for more redirects
if( isset($this->error_data['redirects'][$target]) ){
$redirects++;
if( $redirects > 10 ){
return false;
}
$target = $this->error_data['redirects'][$target]['target'];
return $this->GetTarget($target);
}
//check for target existence
if( isset($gp_index[$target]) ){
return \gp\tool::GetUrl($target);
}
$scripts = \gp\admin\Tools::AdminScripts();
if( isset($scripts[$target]) ){
return \gp\tool::GetUrl($target);
}
return false;
}
public function isGPLink($target){
//has a url scheme (aka protocol)
$reg = '#^[a-zA-Z][a-zA-Z0-9\+\.\-]+:#';
if( preg_match($reg,$target,$matches) ){
return false;
}
//strings beginning with / could be gplinks, they could also links to non-cms managed pages
// we could do additional testing, but we could never be certain what the user intent is
if( strpos($target,'/') === 0 ){
return false;
}
return true;
}
public function Get404(){
global $langmessage,$page;
\gp\tool\Output::AddHeader('Not Found',true,404);
$page->head .= '<meta name="robots" content="noindex,nofollow" />'; //this isn't getting to the template because $page isn't available yet
//message for admins
if( \gp\tool::LoggedIn() ){
if( $this->requested && \gp\tool::SpecialOrAdmin($this->requested) === false ){
$with_spaces = htmlspecialchars($this->requested);
$link = \gp\tool::GetUrl('Admin/Menu/Ajax','cmd=AddHidden&redir=redir&title='.rawurlencode($this->requested)).'" title="'.$langmessage['create_new_file'].'" data-cmd="gpabox';
$message = sprintf($langmessage['DOESNT_EXIST'],$with_spaces,$link);
msg($message);
}
}
echo '<div class="GPAREA filetype-special_missing">';
//Contents of 404 page
$wrap = \gp\tool\Output::ShowEditLink('Admin/Missing');
if( $wrap ){
echo \gp\tool\Output::EditAreaLink($edit_index,'Admin/Missing',$langmessage['edit'],'cmd=edit404',' title="'.$langmessage['404_Page'].'" ');
echo '<div class="editable_area" id="ExtraEditArea'.$edit_index.'">'; // class="edit_area" added by javascript
}
echo self::Get404Output();
if( $wrap ){
echo '</div>';
}
echo '</div>';
}
/**
* Return the custom 404 page content if it exists, otherwise return the default content
*
*/
public function Get404Output(){
if( isset($this->error_data['404_TEXT']) ){
$text = $this->error_data['404_TEXT'];
}else{
$text = self::DefaultContent();
}
return str_replace('{{Similar_Titles}}',$this->SimilarTitles(),$text);
}
/**
* Get a comma separated list of links to titles similar to the requested page
* @return string
*
*/
public function SimilarTitles(){
$similar = $this->SimilarTitleArray($this->requested);
$similar = array_slice($similar,0,7,true);
$result = '';
foreach($similar as $title => $percent_similar){
if ( $title === key($similar) || $percent_similar > 10 ) {
$result .= \gp\tool::Link_Page($title).', ';
}
}
return rtrim($result,', ');
}
/**
* Get a list of existing titles similar to the requested page
* @param string $title of requested page
* @return array of similar titles reverse-numerical sorted by similarity (percent)
*
*/
public function SimilarTitleArray($title){
global $gp_index, $gp_titles;
$similar_titles = [];
$lower = str_replace(' ','_',strtolower($title));
foreach($gp_index as $title => $index){
//skip 'special_missing' page
if( $index == 'special_missing' ){
continue;
}
//skip private pages when not logged-in
if( !\gp\tool::LoggedIn() && isset($gp_titles[$index]['vis']) ){
continue;
}
similar_text($lower,mb_strtolower($title),$percent);
$similar_titles[$index] = [
'title' => $title,
'percent' => $percent,
];
}
uasort($similar_titles, function($a, $b) {
return $b['percent'] - $a['percent'];
});
$similar_titles = \gp\tool\Plugins::Filter('SimilarTitles', [$similar_titles]);
$similar = [];
foreach( $similar_titles as $similar_title ){
$similar[$similar_title['title']] = $similar_title['percent'];
}
return $similar;
}
/**
* Returnt the default content of the 404 page
*
*/
public function DefaultContent(){
global $langmessage;
$text = '<h2>'.$langmessage['Not Found'].'</h2>';
$text .= '<p>';
$text .= $langmessage['OOPS_TITLE'];
$text .= '</p>';
$text .= '<p>';
$text .= '<b>'.$langmessage['One of these titles?'].'</b>';
$text .= '<div class="404_suggestions">{{Similar_Titles}}</div>';
$text .= '</p>';
return $text;
}
}