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

Shortcode parser: fixed number of errors, more major changes, getScBatch will now auto-register batch (no need of registerShortcode() call), added new example of sc handler usage (news), work in progress

This commit is contained in:
secretr
2010-04-25 13:52:14 +00:00
parent 6b7a4f7242
commit e0c8e76f70
6 changed files with 299 additions and 165 deletions

View File

@@ -2124,7 +2124,7 @@ function __autoload($className)
// read the todo for e_shortcode.php related problems
if('shortcodes' == $end)
{
$filename = e_PLUGIN.$tmp[0].'/shortcodes/'; // plugname/shortcodes/
$filename = e_PLUGIN.$tmp[0].'/core/shortcodes/batch/'; // plugname/core/shortcodes/batch/
unset($tmp[0]);
$filename .= implode('_', $tmp).'_shortcodes.php'; // my_shortcodes.php
break;
@@ -2163,7 +2163,7 @@ function __autoload($className)
// register __autoload if possible to prevent its override by
// 3rd party spl_autoload_register calls
if(function_exists('spl_autoload_register'))
if(function_exists('spl_autoload_register') && !defset('E107_DISABLE_AUTOLOAD', false))
{
spl_autoload_register('__autoload');
}

View File

@@ -20,8 +20,9 @@ register_shortcode('news_shortcodes', TRUE);
initShortcodeClass('news_shortcodes');
*/
e107::getScParser()->registerShortcode('news_shortcodes', true)
->initShortcodeClass('news_shortcodes');
// Done via e107::getScBatch('news'); call - see news_class.php
/*e107::getScParser()->registerShortcode('news_shortcodes', true)
->initShortcodeClass('news_shortcodes');*/
class news_shortcodes extends e_shortcode
{

View File

@@ -861,14 +861,29 @@ class e107
/**
* Retrieve registered sc object (batch) by class name
* Note - '_shortcodes' part of the class is added by the method
* <code><?php e107::getScObject('news');</code>
* Note - '_shortcodes' part of the class/override is added by the method
* Override is possible only if class is not already instantiated by shortcode parser
*
* <code><?php
* // core news shortcodes
* e107::getScObject('news');
* // object of plugin_myplugin_my_shortcodes class -> myplugin/core/shortcodes/batch/my_shortcodes.php
* e107::getScObject('my', 'myplugin');
* // news override - plugin_myplugin_news_shortcodes extends news_shortcodes -> myplugin/core/shortcodes/batch/news_shortcodes.php
* e107::getScObject('news', 'myplugin', true);
* // news override - plugin_myplugin_mynews_shortcodes extends news_shortcodes -> myplugin/core/shortcodes/batch/mynews_shortcodes.php
* e107::getScObject('news', 'myplugin', 'mynews');
* </code>
*
* @param string $className
* @param string $pluginName
* @param string|true $overrideClass
* @return e_shortcode
*/
public static function getScBatch($className)
public static function getScBatch($className, $pluginName = null, $overrideClass = null)
{
return self::getScParser()->getScObject($className.'_shortcodes');
if(is_string($overrideClass)) $overrideClass .= '_shortcodes';
return self::getScParser()->getScObject($className.'_shortcodes', $pluginName, $overrideClass);
}
/**

View File

@@ -2132,6 +2132,16 @@ class e_vars
return empty($this->vars);
}
/**
* Check if given data key is set
* @param string $key
* @return boolean
*/
public function isVar($key)
{
return isset($this->vars[$key]);
}
/**
* Magic setter
*
@@ -2171,7 +2181,7 @@ class e_vars
*/
public function __isset($key)
{
return isset($this->vars[$key]);
return $this->isVar($key);
}
/**

View File

@@ -601,7 +601,7 @@ class news {
}
//$loop_uid = $news['news_author']; - no references found
require_once(e_CORE.'shortcodes/batch/news_shortcodes.php');
//require_once(e_CORE.'shortcodes/batch/news_shortcodes.php');
/* DEPRECATED
setScVar('news_shortcodes', 'news_item', $news);
setScVar('news_shortcodes', 'param', $param);

View File

@@ -12,7 +12,10 @@
* $Id$
*/
if (!defined('e107_INIT')) { exit; }
if (!defined('e107_INIT'))
{
exit;
}
/**
*
@@ -41,7 +44,6 @@ function setScVar($className, $scVarName, $value)
return e107::getScParser()->setScVar($className, $scVarName, $value);
}
/**
* FIXME: to be removed
*/
@@ -58,7 +60,6 @@ function initShortcodeClass($class, $force = false, $eVars = null)
return e107::getScParser()->initShortcodeClass($class, $eVars, $force);
}
class e_parse_shortcode
{
protected $scList = array(); // The actual code - added by parsing files or when plugin codes encountered. Array key is the shortcode name.
@@ -67,7 +68,10 @@ class e_parse_shortcode
protected $registered_codes = array(); // Shortcodes added by plugins TODO make it private
protected $scClasses = array(); // Batch shortcode classes - TODO make it private
protected $scOverride = array(); // Array of codes found in override/ dir
protected $eVars = '';
/**
* @var e_vars
*/
protected $eVars = null;
function __construct()
{
@@ -132,7 +136,7 @@ class e_parse_shortcode
}
//register object if required
if(null !== $classObj && (!isset($this->scClasses[$classFunc]) || $force == true))
if (null !== $classObj && (!$this->isScClass($classFunc) || $force == true))
{
$this->scClasses[$classFunc] = $classObj;
}
@@ -158,7 +162,7 @@ class e_parse_shortcode
*/
public function setScVar($className, $scVarName, $value)
{
if(isset($this->scClasses[$className]))
if ($this->isScClass($className))
{
// new way - batch should extend e_shortcode class
if (method_exists($this->scClasses[$className], 'setScVar'))
@@ -166,6 +170,7 @@ class e_parse_shortcode
$this->scClasses[$className]->setScVar($scVarName, $value);
}
else // Old - DEPRECATED
{
$this->scClasses[$className]->$scVarName = $value;
}
@@ -180,13 +185,33 @@ class e_parse_shortcode
* @param string $scFuncName
* @param mixed $param - passed to function
*
* @return mixed|boolean - NULL if class doesn't exist; otherwise whatever the function returns.
* @return mixed|boolean - NULL if class/method doesn't exist; otherwise whatever the function returns.
*/
public function callScFunc($className, $scFuncName, $param = '')
{
if(isset($this->scClasses[$className]))
if ($this->isScClass($className))
{
return call_user_func(array($this->scClasses[$className], $scFuncName), $param);
return method_exists($this->scClasses[$className], $scFuncName) ? call_user_func(array($this->scClasses[$className], $scFuncName), $param) : null;
}
return null;
}
/**
* same as e_parse_shortcode::callScFunc(), but passes the last argument (array)
* to the called method as multiple arguments
*
* @param string $className
* @param string $scFuncName
* @param array $param - arguments passed to function
*
* @return mixed|boolean - NULL if class/method doesn't exist; otherwise whatever the function returns.
*/
protected function callScFuncA($className, $scFuncName, $args = array())
{
if ($this->isScClass($className))
{
// avoid warnings
return method_exists($this->scClasses[$className], $scFuncName) ? call_user_func_array(array($this->scClasses[$className], $scFuncName), $args) : null;
}
return null;
}
@@ -198,28 +223,83 @@ class e_parse_shortcode
* @param boolean $force
* @return e_shortcode
*/
public function initShortcodeClass($class, $eVars = null, $force = false)
public function initShortcodeClass($class, $force = false)
{
if(class_exists($class, false) && ($force || !isset($this->scClasses[$class])))
if (class_exists($class, false) && ($force || !$this->isScClass($className)))
{
$this->scClasses[$class] = new $class($eVars);
$this->scClasses[$class] = new $class();
return $this->scClasses[$class];
}
return null;
}
/**
* Get registered SC object
*
* @param string $className
* @return e_shortcode
*/
public function getScObject($className)
/*public function getScObject($className)
{
if (isset($this->scClasses[$className]))
{
return $this->scClasses[$className];
}
// TODO - throw exception?
return null;
}*/
/**
* Get registered SC object
* Normally you would use the proxy of this method - e107::getScBatch()
* DRAFT!
*
* <code><?php
* // simple use
* e107::getScParser()->getScObject('news_shortcodes');
*
* // plugin override - e107_plugins/myplug/core/shortcodes/batch/news_shortcodes.php -> class plugin_myplug_news_shortcodes
* e107::getScParser()->getScObject('news_shortcodes', 'myplug', true);
*
* // more complex plugin override
* // e107_plugins/myplug/core/shortcodes/batch/news2_shortcodes.php -> class plugin_myplug_news2_shortcodes
* e107::getScParser()->getScObject('news_shortcodes', 'myplug', 'news2_shortcodes');
* </code>
* @param string $className
* @param string $plugName
* @param string $overrideClass if true, $className is used
* @return e_shortcode
*/
public function getScObject($className, $pluginName = null, $overrideClass = null)
{
if ($this->isScClass($className))
{
return $this->scClasses[$className];
}
// defaults
$_class = $_class_fname = $className;
// plugin override
if($overrideClass)
{
if(true === $overrideClass)
{
$overrideClass = $className;
}
// e.g. class plugin_myplug_news_shortcodes
$_class_fname = $overrideClass;
$_class = 'plugin_'.$pluginName.'_'.$overrideClass;
}
$path = ($pluginName ? e_PLUGIN.$pluginName.'/shortcodes/batch/' : e_CORE.'shortcodes/batch/').$_class_fname.'.php';
if (is_readable($path))
{
require_once($path);
if (class_exists($_class, false)) // don't allow __autload()
{
// register instance directly to allow override
$this->scClasses[$className] = new $_class();
$this->registerClassMethods($className);
return $this->scClasses[$className];
}
}
// TODO - throw exception?
return null;
}
@@ -268,7 +348,6 @@ class e_parse_shortcode
return $this;
}
/**
* Register all .sc files found in plugin directories (via pref)
*
@@ -328,37 +407,38 @@ class e_parse_shortcode
continue;
}
$this->registerClassMethods($classFunc, $path);
$this->registerClassMethods($classFunc, $path, false);
}
return $this;
}
/**
* Common Auto-Register function for class methods.
*
* @return e_parse_shortcode
*/
protected function registerClassMethods($classFunc, $path)
protected function registerClassMethods($class, $path, $force = false)
{
//$this->scClasses[$classFunc] = new $classFunc;
$tmp = get_class_methods($class);
$className = is_object($class) ? get_class($class) : $class;
$tmp = get_class_methods($classFunc);
foreach ($tmp as $c)
{
if (strpos($c, 'sc_') === 0)
{
$sc_func = substr($c, 3);
$code = strtoupper($sc_func);
if(!$this->isRegistered($code))
if ($force || !$this->isRegistered($code))
{
$this->registered_codes[$code] = array('type' => 'class', 'path' => $path, 'class' => $classFunc);
$this->registered_codes[$code] = array('type' => 'class', 'path' => $path, 'class' => $className);
}
}
}
return $this;
}
/**
* Register Core Shortcode Batches.
* FIXME - currently loaded all the time (even on front-end)
* FIXME - make it smarter - currently loaded all the time (even on front-end)
*
* @return e_parse_shortcode
*/
@@ -384,10 +464,15 @@ class e_parse_shortcode
public function resetScClass($className, $object)
{
if($this->isScClass($className))
if(null === $object)
{
unset($this->scClasses[$className]);
}
elseif ($this->isScClass($className))
{
$this->scClasses[$className] = $object;
}
return $this;
}
function isScClass($className)
@@ -404,11 +489,8 @@ class e_parse_shortcode
{
$saveParseSCFiles = $this->parseSCFiles; // In case of nested call
$this->parseSCFiles = $useSCFiles;
$this->eVars = null;
if(is_object($eVars)) {
$saveVars = $this->eVars; // In case of nested call
$this->eVars = $eVars;
}
//object support
if (is_object($extraCodes))
@@ -423,6 +505,9 @@ class e_parse_shortcode
//always overwrite object
$this->scClasses[$classname] = $extraCodes;
// auto-register eVars if possible - call it manually?
// $this->callScFunc($classname, 'setVars', $this->eVars);
}
elseif (is_array($extraCodes))
{
@@ -433,7 +518,7 @@ class e_parse_shortcode
}
$ret = preg_replace_callback('#\{(\S[^\x02]*?\S)\}#', array(&$this, 'doCode'), $text);
$this->parseSCFiles = $saveParseSCFiles; // Restore previous value
$this->eVars = null; // reset eVars
$this->eVars = $saveVars; // restore eVars
return $ret;
}
@@ -441,12 +526,17 @@ class e_parse_shortcode
{
global $pref, $e107cache, $menu_pref, $sc_style, $parm, $sql;
if($this->eVars) {
if($this->eVars->$matches[1]) {
if ($this->eVars)
{
if ($this->eVars->isVar($matches[1]))
{
return $this->eVars->$matches[1];
}
}
if(strpos($matches[1], E_NL) !== false) { return $matches[0]; }
if (strpos($matches[1], E_NL) !== false)
{
return $matches[0];
}
if (strpos($matches[1], '='))
{
@@ -506,7 +596,10 @@ class e_parse_shortcode
//shortcode is registered, let's proceed.
if (isset($this->registered_codes[$code]['perms']))
{
if(!check_class($this->registered_codes[$code]['perms'])) { return ''; }
if (!check_class($this->registered_codes[$code]['perms']))
{
return '';
}
}
switch ($this->registered_codes[$code]['type'])
@@ -515,25 +608,36 @@ class e_parse_shortcode
//It is batch shortcode. Load the class and call the method
$_class = $this->registered_codes[$code]['class'];
$_method = 'sc_'.strtolower($code);
if(!isset($this->scClasses[$_class]))
if (!$this->isScClass($_class))
{
if (!class_exists($_class) && $this->registered_codes[$code]['path'])
{
include_once($this->registered_codes[$code]['path']);
}
$this->initShortcodeClass($_class, $this->eVars, false);
//$this->scClasses[$_class] = new $_class;
// make eVars available to the SC object members
//$this->scClasses[$_class]->eVars = $this->eVars;
$this->initShortcodeClass($_class, false);
if(!$this->isScClass($_class))
{
return '';
}
if(method_exists($this->scClasses[$_class], $_method))
// egister passed eVars object on init - call it manually?
// $this->callScFunc($_class, 'setVars', $this->eVars);
}
// FIXME - register passed eVars object - BAD solution - called on EVERY sc method call
// XXX - removal candidate - I really think it should be done manually (outside the parser)
// via e107::getScBatch(name)->setVars($eVars);
// $this->callScFunc($_class, 'setVars', $this->eVars);
$ret = $this->callScFuncA($_class, $_method, array($parm, $sc_mode));
/*if (method_exists($this->scClasses[$_class], $_method))
{
$ret = $this->scClasses[$_class]->$_method($parm, $sc_mode);
}
else
{
echo $_class.'::'.$_method.' NOT FOUND!<br />';
}
}*/
break;
@@ -577,6 +681,7 @@ class e_parse_shortcode
include_once(e_CORE.'shortcodes/single/'.strtolower($code).'.php');
if (class_exists($_class, false)) // prevent __autoload - performance
{
$ret = call_user_func(array($_class, $_function), $parm);
}
@@ -599,7 +704,10 @@ class e_parse_shortcode
if (!isset($scCode))
{
if(E107_DBG_BBSC) { trigger_error('shortcode not found:{'.$code.'}', E_USER_ERROR); }
if (E107_DBG_BBSC)
{
trigger_error('shortcode not found:{'.$code.'}', E_USER_ERROR);
}
return $matches[0];
}
@@ -727,9 +835,8 @@ class e_shortcode
*/
protected $scVars = null;
public function __construct($eVars = null)
public function __construct()
{
$this->setVars($eVars);
$this->scVars = new e_vars();
}
@@ -741,7 +848,8 @@ class e_shortcode
*/
public function setVars($eVars)
{
if(null === $eVars) $eVars = new e_vars();
if (null === $eVars)
$eVars = new e_vars();
$this->eVars = $eVars;
return $this;
}