Skip to content

Instantly share code, notes, and snippets.

@jbroadway
Last active June 6, 2016 19:14
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save jbroadway/1558300 to your computer and use it in GitHub Desktop.
Elefant CMS Subfolder Proxy
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
#RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} \.(js|css)$
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . subfolder.php [L]
</IfModule>
DirectoryIndex subfolder.php index.php

Elefant CMS Subfolder Proxy

This is a proxy script that enables the Elefant CMS to transparently run inside of a subfolder, since the main CMS and framework are optimized to run in the root of a site. Since Elefant is very performance-oriented, the proxy adds only very minimal overhead, and allows all Elefant apps to continue to work as before with no changes at all, automatically adjusting paths in HTML output, HTTP headers, as well as JS and CSS files.

For usage instructions, please see here:

https://www.elefantcms.com/docs/2.0/getting-started/installation

<?php
/**
* Elefant CMS Subfolder Proxy - http://www.elefantcms.com/
*
* Copyright (c) 2012 Johnny Broadway
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* This is a proxy script that will enable Elefant to run inside of a
* subfolder, which the main front controller does not support to keep
* it nice and lightweight and to eliminate the need for extensive
* repetition of a {{prefix}} type template variable.
*
* ## Caveat
*
* This is a workaround, and has certain drawbacks, but it does work.
* It is of course better, whenever possible, to run Elefant in the
* document root directly. The drawbacks are that this script adds
* extra overhead not just to PHP scripts but also in proxying CSS
* and JavaScript files too. Note that it doesn't affect other types
* of files, or files outside of the subfolder in question.
*
* ## Usage
*
* To enable the subfolder proxy, here are the steps you need to take:
*
* 1. Replace the .htaccess file with the following:
*
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} \.(js|css)$
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . subfolder.php [L]
</IfModule>
DirectoryIndex subfolder.php
*
* 2. Drop this file (`subfolder.php`) beside your `index.php` file.
*
* 3. Proceed with the steps from the command line install method.
*
* You should now be able to run Elefant inside of any subfolder of your
* choice.
*/
/**
* Determine the subfolder path, and alter the REQUEST_URI to trick
* the front controller into thinking it's working at the document
* root.
*/
$cwd = str_replace ('\\', '/', getcwd ());
$root = rtrim ($_SERVER['DOCUMENT_ROOT'], '/');
define ('SUB_FOLDER', str_replace ($root, '', $cwd));
$_SERVER['REQUEST_URI'] = preg_replace ('|' . SUB_FOLDER . '|', '', $_SERVER['REQUEST_URI'], 1);
/**
* Pass the request on to the front controller if we're not inside of a
* sub-folder.
*/
if ($_SERVER['DOCUMENT_ROOT'] === getcwd ()) {
require_once ('index.php');
return;
}
/**
* Rewrite absolute references in JavaScript and CSS as well as PHP output.
*
* In JavaScript, we look for anything opening with a quote (single or double)
* followed by a `/` and at least two alphanumeric characters.
*
* In CSS, we only have to look for `url(` references, which makes it a bit
* simpler.
*/
$path = parse_url ($_SERVER['REQUEST_URI'], PHP_URL_PATH);
if (preg_match ('/\.(js|css)$/', $path, $matches)) {
$file = preg_replace ('/^\//', '', $_SERVER['REQUEST_URI']);
if ($matches[1] === 'js') {
header ('Content-Type: application/javascript');
$out = preg_replace ('/(\'|")\/([a-zA-Z0-9_-]{2,}|\1)/', '\1' . SUB_FOLDER . '/\2', file_get_contents ($file));
$out = str_replace (SUB_FOLDER . SUB_FOLDER, SUB_FOLDER, $out);
} else {
header ('Content-Type: text/css');
$out = preg_replace ('/url\(([\'"]?)\//', 'url(\1' . SUB_FOLDER . '/', file_get_contents ($file));
$out = str_replace (SUB_FOLDER . SUB_FOLDER, SUB_FOLDER, $out);
}
header ('Cache-Control: max-age=604800, must-revalidate'); // 1 week
header ('Content-Length: ' . strlen ($out));
echo $out;
return;
}
/**
* Define an exception we can throw to capture faked exit calls
* (via `$controller->quit()`).
*/
class SubfolderException extends Exception {}
/**
* Run the front controller and capture the headers and output.
*/
ob_start ();
try {
require_once ('index.php');
} catch (SubfolderException $e) {
/**
* Catch calls to $controller->quit() and continue.
*/
}
$headers = headers_list ();
$out = ob_get_clean ();
/**
* Alter any headers and re-send them. If the output is empty, we can
* skip the output stage.
*/
foreach ($headers as $header) {
header (
preg_replace (
'/:\/\/' . preg_quote ($_SERVER['HTTP_HOST']) . '\//',
'://' . $_SERVER['HTTP_HOST'] . rtrim (SUB_FOLDER, '/') . '/',
$header
)
);
}
if (empty ($out)) {
return;
}
/**
* Reinstate the gzip output compression if it's enabled in the config
* then send the altered output.
*/
if (! defined ('ELEFANT_ENV')) {
define ('ELEFANT_ENV', getenv ('ELEFANT_ENV') ? getenv ('ELEFANT_ENV') : 'config');
}
$conf = parse_ini_file ('conf/' . ELEFANT_ENV . '.php', true);
if ($conf['General']['compress_output'] && extension_loaded ('zlib')) {
ob_start ('ob_gzhandler');
}
if (strpos ($out, '\/') !== false) {
$out = preg_replace ('/(\'|")\\\\\/([a-zA-Z0-9_-]{2,}|\1)/', '\1' . str_replace ('/', '\\/', SUB_FOLDER) . '\\/\2', $out);
$out = str_replace ('\\' . SUB_FOLDER . '\\' . SUB_FOLDER, '\\' . SUB_FOLDER, $out);
}
$out = preg_replace ('/(\'|")\/([a-zA-Z0-9_-]{2,}|\1)/', '\1' . SUB_FOLDER . '/\2', $out);
$out = str_replace (SUB_FOLDER . SUB_FOLDER, SUB_FOLDER, $out);
echo $out;
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment