1
0
mirror of https://github.com/e107inc/e107.git synced 2025-08-08 15:46:44 +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 // read the todo for e_shortcode.php related problems
if('shortcodes' == $end) 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]); unset($tmp[0]);
$filename .= implode('_', $tmp).'_shortcodes.php'; // my_shortcodes.php $filename .= implode('_', $tmp).'_shortcodes.php'; // my_shortcodes.php
break; break;
@@ -2163,7 +2163,7 @@ function __autoload($className)
// register __autoload if possible to prevent its override by // register __autoload if possible to prevent its override by
// 3rd party spl_autoload_register calls // 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'); spl_autoload_register('__autoload');
} }

View File

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

View File

@@ -861,14 +861,29 @@ class e107
/** /**
* Retrieve registered sc object (batch) by class name * Retrieve registered sc object (batch) by class name
* Note - '_shortcodes' part of the class is added by the method * Note - '_shortcodes' part of the class/override is added by the method
* <code><?php e107::getScObject('news');</code> * 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 * @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); 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 * Magic setter
* *
@@ -2171,7 +2181,7 @@ class e_vars
*/ */
public function __isset($key) 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 //$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 /* DEPRECATED
setScVar('news_shortcodes', 'news_item', $news); setScVar('news_shortcodes', 'news_item', $news);
setScVar('news_shortcodes', 'param', $param); setScVar('news_shortcodes', 'param', $param);

View File

@@ -12,7 +12,10 @@
* $Id$ * $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); return e107::getScParser()->setScVar($className, $scVarName, $value);
} }
/** /**
* FIXME: to be removed * FIXME: to be removed
*/ */
@@ -58,7 +60,6 @@ function initShortcodeClass($class, $force = false, $eVars = null)
return e107::getScParser()->initShortcodeClass($class, $eVars, $force); return e107::getScParser()->initShortcodeClass($class, $eVars, $force);
} }
class e_parse_shortcode 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. 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 $registered_codes = array(); // Shortcodes added by plugins TODO make it private
protected $scClasses = array(); // Batch shortcode classes - 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 $scOverride = array(); // Array of codes found in override/ dir
protected $eVars = ''; /**
* @var e_vars
*/
protected $eVars = null;
function __construct() function __construct()
{ {
@@ -132,7 +136,7 @@ class e_parse_shortcode
} }
//register object if required //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; $this->scClasses[$classFunc] = $classObj;
} }
@@ -158,7 +162,7 @@ class e_parse_shortcode
*/ */
public function setScVar($className, $scVarName, $value) public function setScVar($className, $scVarName, $value)
{ {
if(isset($this->scClasses[$className])) if ($this->isScClass($className))
{ {
// new way - batch should extend e_shortcode class // new way - batch should extend e_shortcode class
if (method_exists($this->scClasses[$className], 'setScVar')) if (method_exists($this->scClasses[$className], 'setScVar'))
@@ -166,6 +170,7 @@ class e_parse_shortcode
$this->scClasses[$className]->setScVar($scVarName, $value); $this->scClasses[$className]->setScVar($scVarName, $value);
} }
else // Old - DEPRECATED else // Old - DEPRECATED
{ {
$this->scClasses[$className]->$scVarName = $value; $this->scClasses[$className]->$scVarName = $value;
} }
@@ -180,13 +185,33 @@ class e_parse_shortcode
* @param string $scFuncName * @param string $scFuncName
* @param mixed $param - passed to function * @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 = '') 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; return null;
} }
@@ -198,28 +223,83 @@ class e_parse_shortcode
* @param boolean $force * @param boolean $force
* @return e_shortcode * @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 $this->scClasses[$class];
} }
return null; return null;
} }
/** /*public function getScObject($className)
* Get registered SC object
*
* @param string $className
* @return e_shortcode
*/
public function getScObject($className)
{ {
if (isset($this->scClasses[$className])) if (isset($this->scClasses[$className]))
{ {
return $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? // TODO - throw exception?
return null; return null;
} }
@@ -268,7 +348,6 @@ class e_parse_shortcode
return $this; return $this;
} }
/** /**
* Register all .sc files found in plugin directories (via pref) * Register all .sc files found in plugin directories (via pref)
* *
@@ -328,37 +407,38 @@ class e_parse_shortcode
continue; continue;
} }
$this->registerClassMethods($classFunc, $path); $this->registerClassMethods($classFunc, $path, false);
} }
return $this; return $this;
} }
/** /**
* Common Auto-Register function for class methods. * 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) foreach ($tmp as $c)
{ {
if (strpos($c, 'sc_') === 0) if (strpos($c, 'sc_') === 0)
{ {
$sc_func = substr($c, 3); $sc_func = substr($c, 3);
$code = strtoupper($sc_func); $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. * 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 * @return e_parse_shortcode
*/ */
@@ -384,10 +464,15 @@ class e_parse_shortcode
public function resetScClass($className, $object) public function resetScClass($className, $object)
{ {
if($this->isScClass($className)) if(null === $object)
{
unset($this->scClasses[$className]);
}
elseif ($this->isScClass($className))
{ {
$this->scClasses[$className] = $object; $this->scClasses[$className] = $object;
} }
return $this;
} }
function isScClass($className) function isScClass($className)
@@ -404,11 +489,8 @@ class e_parse_shortcode
{ {
$saveParseSCFiles = $this->parseSCFiles; // In case of nested call $saveParseSCFiles = $this->parseSCFiles; // In case of nested call
$this->parseSCFiles = $useSCFiles; $this->parseSCFiles = $useSCFiles;
$saveVars = $this->eVars; // In case of nested call
$this->eVars = null;
if(is_object($eVars)) {
$this->eVars = $eVars; $this->eVars = $eVars;
}
//object support //object support
if (is_object($extraCodes)) if (is_object($extraCodes))
@@ -423,6 +505,9 @@ class e_parse_shortcode
//always overwrite object //always overwrite object
$this->scClasses[$classname] = $extraCodes; $this->scClasses[$classname] = $extraCodes;
// auto-register eVars if possible - call it manually?
// $this->callScFunc($classname, 'setVars', $this->eVars);
} }
elseif (is_array($extraCodes)) elseif (is_array($extraCodes))
{ {
@@ -433,7 +518,7 @@ class e_parse_shortcode
} }
$ret = preg_replace_callback('#\{(\S[^\x02]*?\S)\}#', array(&$this, 'doCode'), $text); $ret = preg_replace_callback('#\{(\S[^\x02]*?\S)\}#', array(&$this, 'doCode'), $text);
$this->parseSCFiles = $saveParseSCFiles; // Restore previous value $this->parseSCFiles = $saveParseSCFiles; // Restore previous value
$this->eVars = null; // reset eVars $this->eVars = $saveVars; // restore eVars
return $ret; return $ret;
} }
@@ -441,12 +526,17 @@ class e_parse_shortcode
{ {
global $pref, $e107cache, $menu_pref, $sc_style, $parm, $sql; global $pref, $e107cache, $menu_pref, $sc_style, $parm, $sql;
if($this->eVars) { if ($this->eVars)
if($this->eVars->$matches[1]) { {
if ($this->eVars->isVar($matches[1]))
{
return $this->eVars->$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], '=')) if (strpos($matches[1], '='))
{ {
@@ -506,7 +596,10 @@ class e_parse_shortcode
//shortcode is registered, let's proceed. //shortcode is registered, let's proceed.
if (isset($this->registered_codes[$code]['perms'])) 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']) 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 //It is batch shortcode. Load the class and call the method
$_class = $this->registered_codes[$code]['class']; $_class = $this->registered_codes[$code]['class'];
$_method = 'sc_'.strtolower($code); $_method = 'sc_'.strtolower($code);
if(!isset($this->scClasses[$_class])) if (!$this->isScClass($_class))
{ {
if (!class_exists($_class) && $this->registered_codes[$code]['path']) if (!class_exists($_class) && $this->registered_codes[$code]['path'])
{ {
include_once($this->registered_codes[$code]['path']); include_once($this->registered_codes[$code]['path']);
} }
$this->initShortcodeClass($_class, $this->eVars, false); $this->initShortcodeClass($_class, false);
//$this->scClasses[$_class] = new $_class; if(!$this->isScClass($_class))
// make eVars available to the SC object members {
//$this->scClasses[$_class]->eVars = $this->eVars; 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); $ret = $this->scClasses[$_class]->$_method($parm, $sc_mode);
} }
else else
{ {
echo $_class.'::'.$_method.' NOT FOUND!<br />'; echo $_class.'::'.$_method.' NOT FOUND!<br />';
} }*/
break; break;
@@ -577,6 +681,7 @@ class e_parse_shortcode
include_once(e_CORE.'shortcodes/single/'.strtolower($code).'.php'); include_once(e_CORE.'shortcodes/single/'.strtolower($code).'.php');
if (class_exists($_class, false)) // prevent __autoload - performance if (class_exists($_class, false)) // prevent __autoload - performance
{ {
$ret = call_user_func(array($_class, $_function), $parm); $ret = call_user_func(array($_class, $_function), $parm);
} }
@@ -599,7 +704,10 @@ class e_parse_shortcode
if (!isset($scCode)) 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]; return $matches[0];
} }
@@ -727,9 +835,8 @@ class e_shortcode
*/ */
protected $scVars = null; protected $scVars = null;
public function __construct($eVars = null) public function __construct()
{ {
$this->setVars($eVars);
$this->scVars = new e_vars(); $this->scVars = new e_vars();
} }
@@ -741,7 +848,8 @@ class e_shortcode
*/ */
public function setVars($eVars) public function setVars($eVars)
{ {
if(null === $eVars) $eVars = new e_vars(); if (null === $eVars)
$eVars = new e_vars();
$this->eVars = $eVars; $this->eVars = $eVars;
return $this; return $this;
} }