PHP Get Relative Path from Parent to Included File - php

I have a directory structure like this:
www/
index.php
my-library/
my-library.php
assets/
my-library.css
images/
loading.gif
I need my-library.php to inject stylesheets into index.php. To do so, I need to get the relative path from index.php to my-library/ -- which in this particular case, would simply be "my-library".
From within my-library.php, is it possible for me to acquire this relative path?
Or must index.php supply it, with something like the following?
<?php
require "my-library/my-library.php";
$mlib->linkroot='my-library';
?>
To clarify, below I have included a more detailed representation of what I'm trying to do:
index.php:
<?php require "my-library/my-library.php"; ?>
<!doctype html>
<head>
<title>Testing My Library</title>
<?php $mlib->injectAssets(); ?>
</head>
<body>..</body>
my-library.php:
<?php
class MyLibrary(){
public $rootpath;
public $linkroot;
function __construct(){
$this->rootpath= __DIR__; // absolute path to my library's root directory (for serverside use)
$this->linkroot = "???"; // relative path to my library's root from index.php (for clientside use, like linking in stylesheets)
}
function injectAssets(){
$csslink = $this->linkroot.'/assets/my-library.css';
echo '<link href="'.$csslink.'" rel="stylesheet" />';
}
}
$mlib = new MyLibrary();
?>
The line I'm interested in figuring out, would be $this->linkroot = "???";.
I'm practically trying to acquire the string that was used to include/require the current script.

I got it! I only had to build a Rube Goldberg Machine to do it!
Thanks PHP.
$linkroot = ascertainLinkroot();
function ascertainLinkroot(){
return makeRelativePath(
getTopScriptPath(),
__DIR__
);
}
function getTopScriptPath(){
$backtrace = debug_backtrace(
defined( "DEBUG_BACKTRACE_IGNORE_ARGS")
?DEBUG_BACKTRACE_IGNORE_ARGS
:FALSE );
$top_frame = array_pop($backtrace);
$top_script_path = $top_frame['file'];
return $top_script_path;
}
function makeRelativePath($from,$to){
// Compatibility
$from = is_dir($from) ?rtrim($from,'\/').'/' :$from;
$to = is_dir($to) ?rtrim($to,'\/').'/' :$to;
$from = str_replace('\\','/',$from);
$to = str_replace('\\','/',$to);
//----------------------------
$from = explode('/',$from);
$to = explode('/',$to);
$path = $to;
foreach($from as $depth => $dir) {
if ($dir === $to[$depth]) { // find first non-matching dir
array_shift($path); // ignore it
} else {
$remaining = count($from)-$depth; // get number of remaining dirs to $from
if ($remaining>1){
// add traversals up to first matching dir
$padLength = -(count($path)+$remaining-1);
$path = array_pad($path, $padLength, '..');
break;
} else {
$path[0] = './'.$path[0];
}
}
}
return rtrim(implode('/', $path),'\/');
}
So, basically, I use the makeRelativePath function to calculate a relative path from the top script's absolute path to the current script's absolute directory path (__DIR__).
I realized that I'm actually looking for the relative path to the library from the top script, not just the parent script -- because the top script is the one where clientside assets will need to be referenced in relation to.
Naturally, PHP doesn't just give you the top script's absolute path. On some environments, the top script's path can be available as a $_SERVER variable, however environment independence is important for me, so I had to find a way.
getTopScriptPath was my solution, as it uses debug_backtrace to find it (creepy, I know), but it is the only environment-independent way to fetch it (to my knowledge).
Still hoping for a more elegant solution, but am satisfied that this one works.

I believe this is what you're looking for:
$this->linkroot = basename(pathinfo($_SERVER['REQUEST_URI'], PATHINFO_DIRNAME));
You can remove basename() to get the full path. Basically, you can run the following code:
echo '<pre>';
var_dump($_SERVER);
echo '</pre>';
If the path you're looking for isn't there in some shape or form, then it simply isn't available and you will have no other choice but to hard code it, or at least hard code part of it.

Have you tried doing a relative link from the root? If not, you might try something like this, if I understand your folder structure.
<link href="/my-library/assets/my-library.css" rel="stylesheet" type="text/css" />
Links like this in any page within your site will pull the same stylesheet, up or down the site structure.

Related

get_included_files() for defined path

I am trying to get the names/path of the files that are included in a files with a given path . But the get_included_files() function works only for the files in which it is written.
<?
include_once('/folder1/folder2/xyz.php');
$path = '/abcd.php';
$includeFiles = get_included_files();
?>
I have tried the above code and i am getting only the included files in this file only.
I want to get the name of the included files in abcd.php i.e for the defined path.
Please HELP !!
How about something like this?
array_filter(get_included_files(), function($item) {
return strpos($item, '/path/to/files/') === 0;
});

Laravel function to convert a realpath() to an absolute URL

I have declared a path pointing to a folder like this:
$path = realpath(public_path('uploads'));
This gives me that value: /var/www/mywebsite/public/uploads
Now, I want to turn this into an absolute URL, like this: http://www.mywebsite.com/uploads
Here is what I did:
dd(asset($path)); // Wrong: http://www.mywebsite.com/var/www/mywebsite/public/uploads
dd(url($path); // Same.
dd(asset('uploads')); // Right, but I only want to use $path
Is there a pre-built way to achieve this in Laravel 5?
You were almost there with asset($path).
Just amend this to asset('uploads') and this will resolve to http://www.mywebsite.com/uploads.
The asset URL helper generates a URL to the public folder of your Laravel application. You then just add the folder you want to go to from there.
Yours $path is taken relatively to public folder with public_path('uploads'), so, 'uploads' by itself points to absolute path. Just add host part to it. Like:
$inPublic = 'uploads';
$localPath = realpath(public_path($inPublic));
// then, either
$url = url("/" . trim($inPublic, "/\\"));
// or
$publicPath = realpath(public_path());
$relativePart = str_replace($publicPath, '', $localPath);
$url = url("/" . trim($relativePart, "/\\"));

Manage URL routes in own php framework

I'm creating a PHP Framework and I have some doubts...
The framework takes the url in this way:
http:/web.com/site/index
It takes the first parameter to load controller (site) and then loads the specific action (index).
If you've installed the framework in a base URL works ok, but if you install it in a subfolder like this:
http://web.com/mysubfolder/controller/action
My script parses it as controller = mysubfolder and action = controller.
If you have more subfolders the results will be worst.
This is my Route code:
Class Route
{
private $_htaccess = TRUE;
private $_suffix = ".jsp";
public function params()
{
$url='';
//nombre del directorio actual del script ejecutandose.
//basename(dirname($_SERVER['SCRIPT_FILENAME']));
if($this->_htaccess !== FALSE):
//no está funcionando bien si está en un subdirectorio web, por ej stynat.dyndns.org/subdir/
// muestra el "subdir" como primer parámetro
$url = $_SERVER['REQUEST_URI'];
if(isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING'])):
$url = str_replace("?" . $_SERVER['QUERY_STRING'], '',$url);
endif;
else:
if(isset($_SERVER['PATH_INFO'])):
$url = $_SERVER['PATH_INFO'];
endif;
endif;
$url = explode('/',preg_replace('/^(\/)/','',$url));
var_dump($url);
var_dump($_GET);
}
}
Thanks for any help you can give.
You are missing a base path. The routing script must now where to start when detecting a pattern or route detected.
Pseudo code:
//set the base URI
$base_uri = '/base';
//remove the base URI from the original uri. You can also REGEX or string match against it if you want
$route_uri = str_replace($base_uri,'',$uri);
//perform route matching $route_uri, in your code a simple explode
$url = explode('/',preg_replace('/^(\/)/','',$route_uri));
You can use this with or without RewriteBase for your .htaccess so long as they use the same harness - index.php.
Additionally, you can improve your route match procedure using Regular Expressions function like preg_match and preg_match_all. They let you define a pattern to match against and results to an array of matching strings - see http://php.net/manual/en/function.preg-match.php.
Even if you are creating your own framework, there is no reason not to reuse robust, well tested and documented components, like this Routing component.
Just use Composer, which has become the standard for dependency management in PHP, and you'll be fine. Add as many components as you want to your stack.
And here you have a must read guide on how to make your own framework.
Yes, I think I know how to fix that.
(Disclaimer: I know that you know most of this but I am going to explain everything for others who may not know some of the gotchas)
Using PATH_INFO and .htaccess
There is a trick in php where if you go to a path like:
http://web.com/mysubfolder/index.php/controller/action
you will get "/controller/action" in the $_SERVER['PATH_INFO'] variable
Now what you need to do is take a .htaccess file (or equivalent) and make it tell your php script the current folder depth.
To do this, put the .htaccess file into the "mysubfolder"
mysubfolder
.htaccess
index.php
.htaccess should contain:
RewriteEngine on
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule (.*) index.php/$1
(I used the yii framework manual as reference, I also recommend using the html5 boilerplate)
Basically you set it up to redirect everything to index.php at a specific point in the url.
Now if you visit: http://web.com/mysubfolder/index.php/controller/action
Now you can get the right path "/controller/action" from $_SERVER['PATH_INFO']
Except it's not going to have any value if you visit http://web.com/mysubfolder/ because the .htaccess file will ignore the rewrite because the http://web.com/mysubfolder/ path requests the mysubfolder/index.php which actually exists and gets denied thank yo RewriteCond %{REQUEST_FILENAME} !-f.
ifsetor function
For this you can use this super handy function called ifsetor (I don't remember where I got it)
function ifsetor(&$variable, $default = null) {
return isset($variable)? $variable: $default;
}
What it does is take a reference to a variable that might or might not exist and provide a default if it does not exist without throwing any notices or errors
Now you can use it to take the PATH_INFO variable safely like so
In your index.php
function ifsetor(&$variable, $default = null) {
return isset($variable)? $variable: $default;
}
$path = ifsetor($_SERVER['PATH_INFO'],'/');
var_dump($path);
php 5.4 also has this new shorter ternary format which you can use if you don't care about notices (I do)
$path = $_SERVER['PATH_INFO']?:'/';
Handling the QUERY_STRING
Now tecnically you are not getting a URL, it is merely its path part and will not contain the query_string, for example when visiting
http://web.com/mysubfolder/index.php/test?param=val
you will only get '/test' in the $path variable, to get the query string use the $_SERVER['QUERY_STRING'] variable
index.php
function ifsetor(&$variable, $default = null) {
return isset($variable)? $variable: $default;
}
$path = ifsetor($_SERVER['PATH_INFO'],'/');
$fullpath = ($_SERVER['QUERY_STRING'])? $path.'?'.$_SERVER['QUERY_STRING']:$path;
var_dump($fullpath);
But that might depend on your needs
$_SERVER['QUERY_STRING'] vs $_GET
Also keep in mind that the $_SERVER['QUERY_STRING'] variable is different from the $_GET and $_REQUEST variables because it keeps duplicate parameters from the query string, for example:
Visiting this page
http://web.com/mysubfolder/controller/action?foo=1&foo=2&foo=3
if going to give you a $_SERVER['QUERY_STRING'] that looks like
?foo=1&foo=2&foo=3
While the $_GET variable is going to be an array like this:
array(
'foo'=>'3'
);
If you don't have .htaccess
You can try using the SCRIPT_NAME to your advantage
list($url) = explode('?',$_SERVER['REQUEST_URI']);
list($basepath) = explode('index.php',$_SERVER['SCRIPT_NAME']);
$url = substr($url,strlen($basepath));
If you like to blow up stuff like me :)
Your case
Class Route
{
private $_htaccess = TRUE;
private $_suffix = ".jsp";
public function params()
{
$url='';
//nombre del directorio actual del script ejecutandose.
//basename(dirname($_SERVER['SCRIPT_FILENAME']));
if($this->_htaccess !== FALSE):
//no está funcionando bien si está en un subdirectorio web, por ej stynat.dyndns.org/subdir/
// muestra el "subdir" como primer parámetro
list($url) = explode('?',$_SERVER['REQUEST_URI']);
$basepath = dirname($_SERVER['SCRIPT_NAME']);
$basepath = ($basepath==='/')? $basepath: $basepath.'/';
$url = substr($url,strlen($basepath));
else:
if(isset($_SERVER['PATH_INFO'])):
$url = $_SERVER['PATH_INFO'];
$url = preg_replace('|^/|','',$url);
endif;
endif;
$url = explode('/',$url);
var_dump($url);
var_dump($_GET);
}
}
I hope this helps
P.S. Sorry for the late reply :(
At some point you will have to check the $_SERVER ['HTTP_HOST'] and a config var defined by the programmer/user wich indicates the subfolder(s) where the app is located, and remove the portion you are not interested in from the rest of the URL.
You can check this forum post on the codeigniter formus for some hints.
CodeIgniter uses another different way to route the controller/method internally.
You do the routing by the $_SERVER['PATH_INFO'] value. You use the urls like this: myapp.com/index.php/controller/method .
To avoid showing index.php on the uri you must rely on an Apache rewrite rule, but even with that I think that the CI one is a nice solution, once you have your index file location, you can avoid all the hassle of parsing the URL.
If I am understanding what you are after correctly, then one solution may be to carry on doing what you are doing, but also get the path of the main routing script (using realpath() for example).
If the last folder (or folder before that etc) matches the beginning URL item (or another section), you ignore it and go for the next one.
Just my 2 cents :-).
Within the application configuration script place a variable which will be set to the path the application runs at.
An alternative is to dynamically set that path.
Before the part
$url = explode('/',preg_replace('/^(\/)/','',$url));
strip the location (sub-folder) path out of the $url string using the predefined application path.
This is how i implemented loader.php
<?php
/*#author arun ak
auto load controller class and function from url*/
class loader
{
private $request;
private $className;
private $funcName;
function __construct($folder = array())
{
$parse_res = parse_url($this->createUrl());
if(!empty($folder) && trim($folder['path'],DIRECTORY_SEPARATOR)!='')
{
$temp_path = explode(DIRECTORY_SEPARATOR,trim($parse_res['path'],DIRECTORY_SEPARATOR));
$folder_path = explode(DIRECTORY_SEPARATOR,trim($folder['path'],DIRECTORY_SEPARATOR));
$temp_path = array_diff($temp_path,$folder_path);
if(empty($temp_path))
{
$temp_path = '';
}
}else
{
if(trim($parse_res['path'],DIRECTORY_SEPARATOR)!='')
{
$temp_path = explode(DIRECTORY_SEPARATOR,trim($parse_res['path'],DIRECTORY_SEPARATOR));
}
else
$temp_path ='';
}
if(is_array($temp_path))
{
if(count($temp_path) ==1)
{
array_push($temp_path,'index');
}
foreach($temp_path as $pathname)
{
$this->request .= $pathname.':';
}
}
else $this->request = 'index'.':'.'index';
}
private function createUrl()
{
$pageURL = (#$_SERVER["HTTPS"] == "on") ? "https://" : "http://";
$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
return $pageURL;
}
public function autolLoad()
{
if($this->request)
{
$parsedPath = explode(':',rtrim($this->request,':'));
if(is_file(APPLICATION_PATH.DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.$parsedPath[0].'_controller'.'.php'))
{
include_once(APPLICATION_PATH.DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.$parsedPath[0].'_controller'.'.php');
if(class_exists($parsedPath[0].'_controller'))
{
$class = $parsedPath[0].'_controller';
$obj = new $class();
//$config = new config('localhost','Winkstore','nCdyQyEdqDbBFpay','mawinkcms');
//$connect = connectdb::getinstance();
//$connect->setConfig($config);
//$connection_obj = $connect->connect();
//$db = $connect->getconnection();//mysql link object
//$obj->setDb($db);
$method = $parsedPath[1];
if(method_exists ($obj ,$parsedPath[1] ))
{
$obj->$method();
}else die('class method '.$method.' not defined');
}else die('class '.$parsedPath[0]. ' has not been defined' );
} else die('controller not found plz define one b4 u proceed'.APPLICATION_PATH.DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.$parsedPath[0].'.php');
}else{ die('oops request not set,i know tis is not the correct way to error :)'); }
}
}
Now in my index file
//include_once('config.php');
include_once('connectdb.php');
require_once('../../../includes/db_connect.php');
include_once('view.php');
include_once('abstractController.php');
include_once('controller.php');
include_once('loader.php');
$loader = new loader(array('path'=>DIRECTORY_SEPARATOR.'magsonwink'.DIRECTORY_SEPARATOR.'modules'.DIRECTORY_SEPARATOR.'admin'.DIRECTORY_SEPARATOR.'atom'.DIRECTORY_SEPARATOR));
$loader->autolLoad();
I haven't used the concept of modules.only controller action and view are rendered.
Are you sure you have your htaccess correctly?
I guess if you're placing your framework on subfolder, then you have to change your RewriteBase in htaccess file from / to /subfolder/. it would be something like this:
# on root
RewriteBase /
#on subfolder
RewriteBase /subfolder/
that's only thing I could wonder of that in your case ...
I don't use OOP, but could show you some snippets of how I do things to dynamically detect if I'm in a subdirectory. Too keep it short and to the point I'll only describe parts of it instead of posting all the code.
So I start out with a .htaccess that send every request to redirect.php in which I splice up the $_SERVER['REQUEST_URI'] variable. I use regex to decide what parts should be keys and what should be values (I do this by assigning anything beginning with 0-9 as a value, and anything beginning with a-z as key) and build the array $GET[].
I then check the path to redirect.php and compare that to my $GET array, to decide where the actual URL begins - or in your case, which key is the controller. Would look something like this for you:
$controller = keyname($GET, count(explode('/', dirname($_SERVER['SCRIPT_NAME']))));
And that's it, I have the first part of the URL. The keyname() function looks like this:
/*************************************
* get key name from array position
*************************************/
function keyname ($arr, $pos)
{
$pos--;
if ( ($pos < 0) || ( $pos >= count($arr) ) )
return ""; // set this any way you like
reset($arr);
for($i = 0;$i < $pos; $i++) next($arr);
return key($arr);
}
To get the links pointing right I use a function called fixpath() like this:
print 'link';
And this is how that function looks:
/*************************************
* relative to absolute path
*************************************/
function fixpath ($path)
{
$root = dirname($_SERVER['SCRIPT_NAME']);
if ($root == "\\" || $root == ".") {
$root = "";
}
$newpath = explode('/', $path);
$newpath[0] .= $root;
return implode('/', $newpath);
}
I hope that helps and can give you some inspiration.
Forget about "reinventing the wheel is wrong" claims. They don't have to use our wheels. I walked on the same road a while ago and i'm totally grateful what i get... i hope you will too
When it comes to the answer to your specific problem -which if faced too- there is a very easy solution. it's a new line in .htaccess at root folder...
Just add line below to your root .htaccess file ; (if your subfoler is "subfolder" )
RewriteRule subfolder/ - [L]
This will leave apart this folder from rewriting directives
By using this way you can install as many instances of your framework as you wish. But if you want this to be framework driven then you have to create/change .htaccess within your framework.
Create /myBaseDirectory/public directory and put your files there - like index.php.
This works because Apache sees this directory like base directory.
basically grab the url string after your first slash, and then explode it into an array (i use '/' as a delimiter).
then carefully array_shift off your elements and store them as variables
item 0: controller
item 1: the action / method in that controller
item 2 thru n: the remaining array is your params

Get calling file name from include()

I want to get the name of the file that includes another file from inside the included file.
I know there is the __FILE__ magic constant, but that doesn't help, since it returns the name of the included file, not the including one.
Is there any way to do this? Or is it impossible due to the way PHP is interpreted?
So this question is pretty old, but I was looking for the answer and after leaving here unsatisfied, I came across $_SERVER['SCRIPT_FILENAME']; Of course this works if the php file doing the including is a web page.
This gives you the full path of the "including file" on the server. eg /var/www/index.php. so if you want just the filename, eg index.php, you will need to use basename() eg
basename($_SERVER['SCRIPT_FILENAME']);
So, if in your index.php you have the following line:
<?php include("./somephp.php"); ?>
and in somephp.php you have
echo "this is the file that included me: " . basename($_SERVER['SCRIPT_FILENAME']);
you will get
this is the file that included me: index.php
output to the browser. This also works if the user is accessing your file without explicitly including the filename in the url, eg www.example.com instead of www.example.com/index.php.
Solution
Knowing that the functions used to include files are include, include_once, require and require_once, also knowing that they are reserved words in PHP, meaning that it will not be possible to declare user functions with the same name, and based on wedgwood's idea of using debug_backtrace you can actually work out from what file the include was called.
What we are going to do is iterate over the backtrace untill we find the most recent call to any of the four include functions, and the the file where it was called. The following code demostrate the technique:
function GetIncludingFile()
{
$file = false;
$backtrace = debug_backtrace();
$include_functions = array('include', 'include_once', 'require', 'require_once');
for ($index = 0; $index < count($backtrace); $index++)
{
$function = $backtrace[$index]['function'];
if (in_array($function, $include_functions))
{
$file = $backtrace[$index]['file'];
break;
}
}
return $file;
}
The above code will return the absolute path of the file where the last include happened, if there hasn't been any include it will return false. Note that the file may has been include from a file that was included from another file, the above function only works for the deepest include.
With a simple modification, you can also get the last included file:
function GetIncludedFile()
{
$file = false;
$backtrace = debug_backtrace();
$include_functions = array('include', 'include_once', 'require', 'require_once');
for ($index = 0; $index < count($backtrace); $index++)
{
$function = $backtrace[$index]['function'];
if (in_array($function, $include_functions))
{
$file = $backtrace[$index - 1]['file'];
break;
}
}
return $file;
}
Observations
Note that __FILE__ is not the included file, but the current file. For example:
file A.php:
<?php
function callme()
{
echo __FILE__;
}
?>
file B.php:
<?php
include('A.php');
callme();
?>
file index.php:
<?php
include('B.php');
?>
In the above example, in the context of the file B.php the included file is B.php (and the including file is index.php) but the output of the function callme is the path of A.php because __FILE__ is in A.php.
Also note that $_SERVER['SCRIPT_FILENAME'] will give the the absolute path to the script requested by the client. If $_SERVER['SCRIPT_FILENAME'] == __FILE__ it means that the current file is the requested one, and therefore there probably hasn't been any includes...
The above method checks if the current file is the requested one, but not if it hasn't been included (below is an example of how the requested file can be included). An actual solution to check if there has not been any inclusions could be to check count(get_included_files()) == 1.
The requested file can be an included file in the following way:
file x.php
<?php
$var = 'something';
include('index.php');
?>
file index.php
<?php
if (!isset($var))
{
include('x.php');
exit;
}
echo 'something';
?>
In the above example, the file index.php will include x.php, then x.php will include index.php back, afterwards index.php outputs "something" and returns control to x.php, x.php returns control to index.php and it reaches exit;
This shows that even if index.php was the requested script, it was also included from another script.
I can't find the easy way to cover this.
But If the including one is really important to you, you could hack it with some global variable and your own include function.
e.g.
<?php
$g_including_files = array();
function my_include($file) {
$bt = debug_backtrace();
global $g_including_files;
$g_including_files[basename($file)] = $bt[0]['file'];
return include($file);
}
May that be helpful for you :)
This is actually just a special case of what PHP templating engines do. Consider having this function:
function ScopedInclude($file, $params = array())
{
extract($params);
include $file;
}
Then A.php can include C.php like this:
<?php
// A.php
ScopedInclude('C.php', array('includerFile' => __FILE__));
Additionally, B.php can include C.php the same way without trouble.
<?php
// B.php
ScopedInclude('C.php', array('includerFile' => __FILE__));
C.php can know its includer by looking in the $params array.
<?php
// C.php
echo $includerFile;

Configuring HTMLPurifier to display external links as plain text

I am trying to configure HTMLPurifier to only display external links as plain text. I used DisplayLinkURI option but it display all links as a plain text. is there any configuration for that? here is my code:
$mySite='mysite';
$externalSite='external';
require_once 'include/htmlpurifier/library/HTMLPurifier.auto.php';
$Config = HTMLPurifier_Config::createDefault();
$Config->set('AutoFormat.DisplayLinkURI', true);
$purifier = new HTMLPurifier($Config);
$mySite= $purifier->purify($mySite);
$externalSite=$purifier->purify($externalSite);
echo $mySite;
echo $externalSite;
The output is
<a>mysite</a> (http://www.mysite.com/)
<a>external</a> (http://www.external.com/)
I want the output to be like this:
mysite
<a>external</a> (http://www.external.com/)
Update:
I want to keep external links for images without change. I only need to convert hyperlinks to plain text.
I believe this is the one you're looking for
http://htmlpurifier.org/live/configdoc/plain.html#URI.DisableExternal
There's an option named URI.DisableExternal and AutoFormat.Linkify. Set them both to TRUE and see what happens.
http://htmlpurifier.org/live/configdoc/plain.html#URI.DisableExternal
http://htmlpurifier.org/live/configdoc/plain.html#AutoFormat.Linkify
And AutoFormat.DisplayLinkURI disables all the links. I suggest you use both the above instead of AutoFormat.DisplayLinkURI.
http://htmlpurifier.org/live/configdoc/plain.html#AutoFormat.DisplayLinkURI
Ok, I succeeded to add a custom injector to HTMLPurifier, here it is:
First, Create a "DisplayRemoteLinkURI.php" in "include\htmlpurifier\library\HTMLPurifier\Injector" and write this in it
<?php
class HTMLPurifier_Injector_DisplayRemoteLinkURI extends HTMLPurifier_Injector
{
public $name = 'DisplayRemoteLinkURI';
public $needed = array('a');
public function handleElement(&$token) {
}
public function handleEnd(&$token) {
if (isset($token->start->attr['href'])){
$url = $token->start->attr['href'];
if($this->is_remote($url)){
unset($token->start->attr['href']);
$token = array($token, new HTMLPurifier_Token_Text(" ($url)"));
}
} else {
// nothing to display
}
}
public function is_remote($path){
$urlvar = parse_url($path);
$remote_schemes = array("mailto");
$local_schemes = array("javascript");
if(in_array($urlvar["scheme"],$remote_schemes)){
return true;
}else if(in_array($urlvar["scheme"],$local_schemes)){
return false;
}else{
if(empty($urlvar["host"]) || $urlvar["host"]==$_SERVER["HTTP_HOST"]){
return false;
}else{
return true;
}
}
}
}
?>
And then create another file named "AutoFormat.DisplayRemoteLinkURI.txt" in "include\htmlpurifier\library\HTMLPurifier\ConfigSchema\schema" and add this :
AutoFormat.DisplayRemoteLinkURI
TYPE: bool
VERSION: 3.2.0
DEFAULT: false
--DESCRIPTION--
<p>
This directive turns on the in-text display of Remote URIs in <a> tags, and disables
those links. For example, example becomes
example (<a>http://example.com</a>).
</p>
--# vim: et sw=4 sts=4
After that, Add this line
require 'HTMLPurifier/Injector/DisplayRemoteLinkURI.php';
under
require 'HTMLPurifier/Injector/DisplayLinkURI.php';
in include\htmlpurifier\library\HTMLPurifier.includes.php
Then, Add this line
require_once $__dir . '/HTMLPurifier/Injector/DisplayRemoteLinkURI.php';
under
require_once $__dir . '/HTMLPurifier/Injector/DisplayLinkURI.php';
in include\htmlpurifier\library\HTMLPurifier.safe-includes.php
After these edits, if your files are at local, run cmd.exe and go to your php directory. Then run "include/HTMLPurifier/maintenance/generate-schema-cache.php" from php.exe.
Or if you want to do this via browser, rename your .htaccess file inside "include/HTMLPurifier/maintenance/" to something else for a while, then add this line inside "generate-schema-cache.php" on the first line after the <?php tag;
php_set_env("PHP_IS_CLI",true);
and then run this file from browser. After you see "Saving schema.. done!", rename your .htaccess file back.
Then in your script, use "AutoFormat.DisplayRemoteLinkURI" as config, and voila!
Note that the is_remote() function inside the first file I gave here might be not so good, and I couldn't find a script that checks if a link is remote or local, so you might alter it later if you need.

Categories