1
0
mirror of https://github.com/e107inc/e107.git synced 2025-08-05 06:07:32 +02:00

Support for namespaced classes; added e_shims

e_shims is an e107 v2-compatible class for the first namespaced core
class, e107\Shims\All.

e107\Shims\All is built from the e107\Shims\InternalShims trait.

e107\Shims\InternalShims currently implements a resilient replacement
for the PHP internal readfile(), which is needed by issue #3528.

As for how the new namespaced classes are handled, the e107 class
(e107_handlers/e107_class.php) has an updated e107::autoload() which
detects namespaced classes and goes to e107::autoload_namespaced().

Namespaced classes handled by e107 are in the \e107 top-level namespace,
and all sub-levels match directory paths under e_HANDLER.
This commit is contained in:
Nick Liu
2018-10-31 07:27:38 -05:00
parent 55b4cf4d03
commit 60056deb93
3 changed files with 144 additions and 20 deletions

View File

@@ -0,0 +1,63 @@
<?php
/**
* e107 website system
*
* Copyright (C) 2008-2018 e107 Inc (e107.org)
* Released under the terms and conditions of the
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
*
* Shims for PHP internal functions
*/
namespace e107\Shims;
trait InternalShims
{
/**
* Outputs a file
*
* Resilient replacement for PHP internal readfile()
*
* @see https://github.com/e107inc/e107/issues/3528 Why this method was implemented
* @param string $filename The filename being read.
* @param bool $use_include_path You can use the optional second parameter and set it to TRUE,
* if you want to search for the file in the include_path, too.
* @param resource $context A context stream resource.
* @return int|bool Returns the number of bytes read from the file.
* If an error occurs, FALSE is returned.
*/
public static function readfile($filename, $use_include_path = FALSE, $context = NULL)
{
$output = @readfile($filename, $use_include_path, $context);
if ($output === NULL)
{
return self::readfile_alt($filename, $use_include_path, $context);
}
return $output;
}
/**
* Outputs a file
*
* Alternative implementation using file streams
*
* @param $filename
* @param bool $use_include_path
* @param resource $context
* @return bool|int
*/
public static function readfile_alt($filename, $use_include_path = FALSE, $context = NULL)
{
// fopen() silently returns false if there is no context
if (!is_resource($context)) $context = stream_context_create();
$handle = @fopen($filename, 'rb', $use_include_path, $context);
if ($handle === FALSE) return FALSE;
while (!feof($handle))
{
echo(fread($handle, 8192));
}
fclose($handle);
return filesize($filename);
}
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* e107 website system
*
* Copyright (C) 2008-2018 e107 Inc (e107.org)
* Released under the terms and conditions of the
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
*
* Shims for PHP internal functions
*/
namespace e107\Shims
{
class All
{
use InternalShims;
}
class Internal
{
use InternalShims;
}
}
// e107 v2-style classes
namespace
{
class e_shims extends \e107\Shims\All
{
}
}

View File

@@ -203,6 +203,7 @@ class e107
'e_parse_shortcode' => '{e_HANDLER}shortcode_handler.php', 'e_parse_shortcode' => '{e_HANDLER}shortcode_handler.php',
'e_plugin' => '{e_HANDLER}plugin_class.php', 'e_plugin' => '{e_HANDLER}plugin_class.php',
'e_ranks' => '{e_HANDLER}e_ranks_class.php', 'e_ranks' => '{e_HANDLER}e_ranks_class.php',
'e_shims' => '{e_HANDLER}Shims/e_shims.php',
'e_shortcode' => '{e_HANDLER}shortcode_handler.php', 'e_shortcode' => '{e_HANDLER}shortcode_handler.php',
'e_system_user' => '{e_HANDLER}user_model.php', 'e_system_user' => '{e_HANDLER}user_model.php',
'e_theme' => '{e_HANDLER}theme_handler.php', 'e_theme' => '{e_HANDLER}theme_handler.php',
@@ -4613,31 +4614,31 @@ class e107
{ {
$_data = self::getSession()->get('__sessionBrowserCache'); $_data = self::getSession()->get('__sessionBrowserCache');
if(!is_array($_data)) $_data = array(); if(!is_array($_data)) $_data = array();
if(null === $set) if(null === $set)
{ {
return in_array(e_REQUEST_URI, $_data); return in_array(e_REQUEST_URI, $_data);
} }
// remove e_REQUEST_URI from the set // remove e_REQUEST_URI from the set
if(false === $set) if(false === $set)
{ {
$check = array_search(e_REQUEST_URI, $_data); $check = array_search(e_REQUEST_URI, $_data);
if(false !== $check) if(false !== $check)
{ {
unset($_data[$check]); unset($_data[$check]);
self::getSession()->set('__sessionBrowserCache', $_data); self::getSession()->set('__sessionBrowserCache', $_data);
return; return;
} }
} }
if(true === $set) if(true === $set)
{ {
$set = e_REQUEST_URI; $set = e_REQUEST_URI;
} }
if(empty($set) || !is_string($set) || in_array($set, $_data)) return; if(empty($set) || !is_string($set) || in_array($set, $_data)) return;
$_data[] = $set; $_data[] = $set;
self::getSession()->set('__sessionBrowserCache', array_unique($_data)); self::getSession()->set('__sessionBrowserCache', array_unique($_data));
} }
@@ -4669,7 +4670,7 @@ class e107
* If $do_return, will always return with ban status - TRUE for OK, FALSE for banned. * If $do_return, will always return with ban status - TRUE for OK, FALSE for banned.
* If return permitted, will never display a message for a banned user; otherwise will display any message then exit * If return permitted, will never display a message for a banned user; otherwise will display any message then exit
* FIXME - moved to ban helper, replace all calls * FIXME - moved to ban helper, replace all calls
* *
* *
* @param string $query * @param string $query
* @param boolean $show_error * @param boolean $show_error
@@ -4720,11 +4721,11 @@ class e107
* @param string $div divider * @param string $div divider
* @return string encoded IP * @return string encoded IP
*/ */
public function ipEncode($ip, $div = ':') public function ipEncode($ip, $div = ':')
{ {
return self::getIPHandler()->ipEncode($ip); return self::getIPHandler()->ipEncode($ip);
} }
/** /**
* Takes an encoded IP address - returns a displayable one * Takes an encoded IP address - returns a displayable one
@@ -4833,14 +4834,14 @@ class e107
{ {
return spl_autoload_register($function); return spl_autoload_register($function);
} }
foreach ($registered as $r) foreach ($registered as $r)
{ {
spl_autoload_unregister($r); spl_autoload_unregister($r);
} }
$result = spl_autoload_register($function); $result = spl_autoload_register($function);
foreach ($registered as $r) foreach ($registered as $r)
{ {
if(!spl_autoload_register($r)) $result = false; if(!spl_autoload_register($r)) $result = false;
} }
@@ -4849,7 +4850,7 @@ class e107
/** /**
* Former __autoload, generic core autoload logic * Former __autoload, generic core autoload logic
* *
* Magic class autoload. * Magic class autoload.
* We are raising plugin structure standard here - plugin auto-loading works ONLY if * We are raising plugin structure standard here - plugin auto-loading works ONLY if
* classes live inside 'includes' folder. * classes live inside 'includes' folder.
@@ -4886,6 +4887,14 @@ class e107
{ {
return; return;
} }
// Detect namespaced class
if (strpos($className, '\\') !== false)
{
self::autoload_namespaced($className);
return;
}
$tmp = explode('_', $className); $tmp = explode('_', $className);
//echo 'autoloding...'.$className.'<br />'; //echo 'autoloding...'.$className.'<br />';
@@ -4894,7 +4903,7 @@ class e107
case 'plugin': // plugin handlers/shortcode batches case 'plugin': // plugin handlers/shortcode batches
array_shift($tmp); // remove 'plugin' array_shift($tmp); // remove 'plugin'
$end = array_pop($tmp); // check for 'shortcodes' end phrase $end = array_pop($tmp); // check for 'shortcodes' end phrase
if (!isset($tmp[0]) || !$tmp[0]) if (!isset($tmp[0]) || !$tmp[0])
{ {
if($end) if($end)
@@ -4905,7 +4914,7 @@ class e107
} }
return; // In case we get an empty class part return; // In case we get an empty class part
} }
// Currently only batches inside shortcodes/ folder are auto-detected, // Currently only batches inside shortcodes/ folder are auto-detected,
// read the todo for e_shortcode.php related problems // read the todo for e_shortcode.php related problems
if('shortcodes' == $end) if('shortcodes' == $end)
@@ -4919,13 +4928,13 @@ class e107
{ {
$tmp[] = $end; // not a shortcode batch - append the end phrase again $tmp[] = $end; // not a shortcode batch - append the end phrase again
} }
// Handler check // Handler check
$tmp[0] .= '/includes'; //folder 'includes' is not part of the class name $tmp[0] .= '/includes'; //folder 'includes' is not part of the class name
$filename = e_PLUGIN.implode('/', $tmp).'.php'; $filename = e_PLUGIN.implode('/', $tmp).'.php';
//TODO add debug screen Auto-loaded classes - ['plugin: '.$filename.' - '.$className]; //TODO add debug screen Auto-loaded classes - ['plugin: '.$filename.' - '.$className];
break; break;
default: //core libraries, core shortcode batches default: //core libraries, core shortcode batches
// core SC batch check // core SC batch check
$end = array_pop($tmp); $end = array_pop($tmp);
@@ -4934,12 +4943,12 @@ class e107
$filename = e_CORE.'shortcodes/batch/'.$className.'.php'; // core shortcode batch $filename = e_CORE.'shortcodes/batch/'.$className.'.php'; // core shortcode batch
break; break;
} }
$filename = self::getHandlerPath($className, true); $filename = self::getHandlerPath($className, true);
//TODO add debug screen Auto-loaded classes - ['core: '.$filename.' - '.$className]; //TODO add debug screen Auto-loaded classes - ['core: '.$filename.' - '.$className];
break; break;
} }
if(!empty($filename) && is_file($filename)) // Test with chatbox_menu if(!empty($filename) && is_file($filename)) // Test with chatbox_menu
{ {
// autoload doesn't REQUIRE files, because this will break things like call_user_func() // autoload doesn't REQUIRE files, because this will break things like call_user_func()
@@ -4947,6 +4956,27 @@ class e107
} }
} }
/**
* Autoloading logic for namespaced classes
*
* @param $className
* @return void
*/
private static function autoload_namespaced($className)
{
$levels = explode('\\', $className);
// Guard against classes that are not ours
if ($levels[0] != 'e107') return;
$levels[0] = e_HANDLER;
$classPath = implode('/', $levels).'.php';
if (is_file($classPath) && is_readable($classPath))
{
include($classPath);
}
}
public function __get($name) public function __get($name)
{ {
switch ($name) switch ($name)