registerShortcode($classFunc, $codes, $path, $force);
}
/**
* FIXME: to be removed
*/
function setScVar($className, $scVarName, $value)
{
return e107::getScParser()->setScVar($className, $scVarName, $value);
}
/**
* FIXME: to be removed (once event calendar changed)
*/
function callScFunc($className, $scFuncName, $param = '')
{
return e107::getScParser()->callScFunc($className, $scFuncName, $param);
}
/**
* FIXME: to be removed
*/
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.
protected $parseSCFiles; // True if individual shortcode files are to be used
protected $addedCodes = NULL; // Pointer to a class or array to be used on a single call
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/shortcodes dir
protected $scBatchOverride = array(); // Array of codes found in override/shortcodes/batch dir
protected $ignoreCodes = array(); // Shortcodes to be ignored and remain unchanged. (ie. {THEME}, {e_PLUGIN} etc. )
protected $addonOverride = array(); // Overrides coming from e_shortcode.php
/**
* @var e_vars
*/
protected $eVars = null;
/**
* Wrappers array for the current parsing cycle, see contact_template.php and $CONTACT_WRAPPER variable
* @var array
*/
protected $wrappers = array();
protected $wrapper = null; // current wrapper being processed.
protected $wrapperDebugDone = array();
/**
* Former $sc_style global variable. Internally used - performance reasons
* @var array
*/
protected $sc_style = array();
function __construct()
{
$this->parseSCFiles = true; // Default probably never used, but make sure its defined.
$this->ignoreCodes = e107::getParser()->getUrlConstants(); // ignore all URL shortcodes. ie. {e_PLUGIN}
$this->loadOverrideShortcodes();
$this->loadThemeShortcodes();
$this->loadPluginShortcodes();
$this->loadPluginSCFiles();
//$this->loadCoreShortcodes(); DEPRECATED
}
/**
* Register shortcode
* $classFunc could be function name, class name or object
* $code could be 'true' when class name/object is passed to automate the
* registration of shortcode methods
*
* @param mixed $classFunc
* @param mixed $codes
* @param string $path
* @param boolean $force override
* @return e_parse_shortcode
*/
function registerShortcode($classFunc, $codes, $path = '', $force = false)
{
//If codes is set to true, let's go get a list of shortcode methods
if ($codes === true)
{
$codes = array();
$tmp = get_class_methods($classFunc);
foreach ($tmp as $c)
{
if (strpos($c, 'sc_') === 0)
{
$codes[] = substr($c, 3);
}
}
unset($tmp);
}
//Register object feature
$classObj = null;
if (is_object($classFunc))
{
$classObj = $classFunc;
$classFunc = get_class($classObj);
}
//We only register these shortcodes if they have not already been registered in some manner
//ie theme or other plugin .sc files
if (is_array($codes))
{
foreach ($codes as $code)
{
$code = strtoupper($code);
if ((!$this->isRegistered($code) || $force == true) && !$this->isOverride($code))
{
$this->registered_codes[$code] = array('type' => 'class', 'path' => $path, 'class' => $classFunc);
}
}
//register object if required
if (null !== $classObj && (!$this->isScClass($classFunc) || $force == true))
{
$this->scClasses[$classFunc] = $classObj;
}
}
else
{
$codes = strtoupper($codes);
if ((!$this->isRegistered($codes) || $force == true) && !$this->isOverride($codes))
{
$this->registered_codes[$codes] = array('type' => 'func', 'path' => $path, 'function' => $classFunc);
}
}
return $this;
}
/**
* Add value to already registered SC object
*
* @param string $className
* @param string $scVarName
* @param mixed $value
* @return e_parse_shortcode
*/
public function setScVar($className, $scVarName, $value)
{
if ($this->isScClass($className))
{
// new way - batch should extend e_shortcode class
if (method_exists($this->scClasses[$className], 'setScVar'))
{
$this->scClasses[$className]->setScVar($scVarName, $value);
}
else // Old - DEPRECATED
{
$this->scClasses[$className]->$scVarName = $value;
}
}
return $this;
}
/**
* Call function on an already registered SC object
*
* @param string $className
* @param string $scFuncName
* @param mixed $param - passed to function
*
* @return mixed|boolean - NULL if class/method doesn't exist; otherwise whatever the function returns.
*/
public function callScFunc($className, $scFuncName, $param = '')
{
if ($this->isScClass($className))
{
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;
}
/**
* Create shortcode object - don't forget you still can use e_shortcode.php
*
* @param string $class
* @param boolean $force
* @return e_shortcode
*/
public function initShortcodeClass($class, $force = false)
{
if (class_exists($class, false) && ($force || !$this->isScClass($class)))
{
$this->scClasses[$class] = new $class();
if(method_exists($this->scClasses[$class], 'init'))
{
$this->scClasses[$class]->init();
}
if(!empty($this->scClasses[$class]->override))
{
$methods = get_class_methods($class);
foreach($methods as $meth)
{
if(substr($meth,0,3) == 'sc_')
{
$this->addonOverride[$meth] = $class;
}
}
}
return $this->scClasses[$class];
}
return null;
}
/**
* Get registered SC object
* Normally you would use the proxy of this method - e107::getScBatch()
* Global File Override ClassName/Path examples:
* 1. Core signup shortcodes
* - Origin ClassName: signup_shortcodes
* - Origin Location: core/shortcodes/batch/signup_shortcodes.php
* - File Override ClassName: override_signup_shortcodes
* - File Override Location: core/override/shortcodes/batch/signup_shortcodes.php
*
* 2. Plugin 'gallery' global shortcode batch (e_shortcode.php)
* - Origin ClassName: gallery_shortcodes //FIXME Should be gallery_shortcode? (more below)
* - Origin Location: plugins/gallery/e_shortcode.php
* - File Override ClassName: override_gallery_shortcodes
* - File Override Location: core/override/shortcodes/batch/gallery_shortcodes.php
*
* 3. Plugin 'forum' regular shortcode batch
* - Origin ClassName: plugin_forum_view_shortcodes //FIXME Should be forum_shortcodes? (more below)
* - Origin Location: plugins/forum/shortcodes/batch/view_shortcodes.php
* - File Override ClassName: override_plugin_forum_view_shortcodes
* - File Override Location: core/override/shortcodes/batch/forum_view_shortcodes.php
*
* getScObject('news_shortcodes'); // For Globally Registered shortcodes, including plugins using e_shortcode.php
*
* // plugin override - e107_plugins/myplug/shortcodes/batch/news_shortcodes.php -> class plugin_myplug_news_shortcodes
* e107::getScParser()->getScObject('news_shortcodes', 'myplug', true);
*
* // more complex plugin override
* // e107_plugins/myplug/shortcodes/batch/news2_shortcodes.php -> class plugin_myplug_news2_shortcodes
* e107::getScParser()->getScObject('news_shortcodes', 'myplug', 'news2_shortcodes');
*
* @param string $className
* @param string $plugName if true className is used., if string, string value is used.
* @param string $overrideClass if true, $className is used
* @return e_shortcode
*/
public function getScObject($className, $pluginName = null, $overrideClass = null)
{
/* FIXME Discuss Generic plugin Class naming. (excluding specific calls with $overrideClass.
// Defaults should be:
e_shortcode.php = {plugin}_shortcode
{plugin}_shortcodes.php = {plugin}_shortcodes
*/
if(trim($className)==""){ return; }
$_class_fname = $className;
if($pluginName === TRUE) //XXX When called manually by a plugin, not e_shortcode.php eg. $sc = e107::getScBatch('faqs',TRUE); for faqs_shortcode.php with class faqs_shortcode
{
$pluginName = str_replace("_shortcodes","",$className);
$manualCall = true;
}
elseif(is_string($pluginName))
{
// FIXME "plugin_ " should NOT be used or be necessary.
// FIXME Core classes should use special naming to avoid comflicts, not plugins.
$className = 'plugin_'.$pluginName.'_'.str_replace('/', '_', $className);
}
$globalOverride = $this->isBatchOverride(str_replace('plugin_', '', $className));
// forced override
if($overrideClass)
{
if(true === $overrideClass)
{
$overrideClass = $className;
}
// e.g. class plugin_myplug_news_shortcodes
if($pluginName != null)
{
$_class_fname = $overrideClass;
$className = 'plugin_'.$pluginName.'_'.str_replace('/', '_', $overrideClass);
}
else
{
$className = $overrideClass;
}
}
if($className == '_theme__shortcodes') // Check for theme shortcode batch. - @see header_default.php //XXX Discuss.
{
$className = 'theme_shortcodes';
$path = THEME.'theme_shortcodes.php';
}
elseif(!$pluginName)
{
if(!$globalOverride)
{
$path = e_CORE.'shortcodes/batch/'.$_class_fname.'.php';
}
else
{
$path = e_CORE.'override/shortcodes/batch/'.$_class_fname.'.php';
$className = 'override_'.$className;
}
}
else
{
if(!$globalOverride)
{
// do nothing if it's e_shortcode batch global
if($pluginName.'_shortcodes' !== $className || $manualCall == true) // manual call by plugin, not e_shortcode.php
{
// BC - required.
$pathBC = e_PLUGIN.$pluginName.'/';
$path = (is_readable($pathBC.$_class_fname.'.php') ? $pathBC : e_PLUGIN.$pluginName.'/shortcodes/batch/').$_class_fname.'.php';
}
}
else
{
$path = e_CORE.'override/shortcodes/batch/'.$pluginName.'_'.$_class_fname.'.php';
$className = 'override_'.$className;
}
}
// Includes global Shortcode Classes (e_shortcode.php) or already loaded batch
if ($this->isScClass($className))
{
return $this->scClasses[$className];
}
// If it already exists - don't include it again.
if (class_exists($className, false)) // don't allow __autoload()
{
// $this->registerClassMethods($className, $path); // XXX Global registration should happen separately - here we want only the object.
$this->scClasses[$className] = new $className();
return $this->scClasses[$className];
}
if (is_readable($path))
{
require_once($path);
if (class_exists($className, false)) // don't allow __autoload()
{
// register instance directly to allow override
$this->scClasses[$className] = new $className();
// $this->registerClassMethods($className, $path); // XXX Global registration should happen separately - here we want only the object.
return $this->scClasses[$className];
}
elseif(E107_DBG_BBSC || E107_DBG_SC)
{
// echo "
To use, add to the file '.$wrapTmpl.'_template.php:'); } if (isset($ret) && ($ret != '' || is_numeric($ret))) { // Wrapper support - see contact_template.php if(isset($this->wrappers[$code]) && !empty($this->wrappers[$code])) // eg: $NEWS_WRAPPER['view']['item']['NEWSIMAGE'] { list($pre, $post) = explode("{---}", $this->wrappers[$code], 2); $ret = $pre.$ret.$post; } elseif(!empty($fullShortcodeKey) && !empty($this->wrappers[$fullShortcodeKey]) ) // eg: $NEWS_WRAPPER['view']['item']['NEWSIMAGE: item=1'] { list($pre, $post) = explode("{---}", $this->wrappers[$fullShortcodeKey], 2); $ret = $pre.$ret.$post; } else { //if $sc_mode exists, we need it to parse $sc_style if ($sc_mode) { $code = $code.'|'.$sc_mode; } if (is_array($this->sc_style) && array_key_exists($code, $this->sc_style)) { $pre = $post = ''; // old way - pre/post keys if(is_array($this->sc_style[$code])) { if (isset($this->sc_style[$code]['pre'])) { $pre = $this->sc_style[$code]['pre']; } if (isset($this->sc_style[$code]['post'])) { $post = $this->sc_style[$code]['post']; } } // new way - same format as wrapper else { list($pre, $post) = explode("{---}", $this->sc_style[$code], 2); } $ret = $pre.$ret.$post; } } } if (E107_DBG_SC || E107_DBG_TIMEDETAILS) { $sql->db_Mark_Time("(After SC {$code})"); } if (E107_DBG_BBSC || E107_DBG_SC || E107_DBG_TIMEDETAILS) { global $db_debug; $other = array(); if(!empty($_type)) { $other['type'] = $_type; } if(!empty($_class)) { $other['class'] = $_class; } if(!empty($_function)) { $other['function'] = $_function; } if(!empty($_path)) { $other['path'] = str_replace('../','',$_path); } if($this->debug_legacy) { $other = $this->debug_legacy; } if(!empty($this->wrappers[$code])) { $other['wrapper'] = $this->wrappers[$code]; } elseif(!empty($this->wrappers[$fullShortcodeKey]) ) { $other['wrapper'] = $this->wrappers[$fullShortcodeKey]; } $info = (isset($this->registered_codes[$code])) ? print_a($this->registered_codes[$code],true) : print_a($other,true); $tmp = isset($debugParm) ? $debugParm : $parm; $db_debug->logCode(2, $code, $tmp, $info); } return isset($ret) ? $ret : ''; } function parse_scbatch($fname, $type = 'file') { global $e107cache, $eArrayStorage; $cur_shortcodes = array(); if ($type == 'file') { $batch_cachefile = 'nomd5_scbatch_'.md5($fname); // $cache_filename = $e107cache->cache_fname("nomd5_{$batchfile_md5}"); $sc_cache = $e107cache->retrieve_sys($batch_cachefile); if (!$sc_cache) { $sc_batch = file($fname); } else { $cur_shortcodes = e107::unserialize($sc_cache); $sc_batch = ""; } } else { $sc_batch = $fname; } $this->debug_legacy = array('type'=>$type, 'path'=> str_replace(e_ROOT,"",$fname)); if ($sc_batch) { $cur_sc = ''; foreach ($sc_batch as $line) { if (trim($line) == 'SC_END') { $cur_sc = ''; } if ($cur_sc) { $cur_shortcodes[$cur_sc] .= $line; } if (preg_match('#^SC_BEGIN (\w*).*#', $line, $matches)) { $cur_sc = $matches[1]; $cur_shortcodes[$cur_sc] = varset($cur_shortcodes[$cur_sc], ''); } } if ($type == 'file') { $sc_cache = $eArrayStorage->WriteArray($cur_shortcodes, false); $e107cache->set_sys($batch_cachefile, $sc_cache); } } foreach (array_keys($cur_shortcodes) as $cur_sc) { if (array_key_exists($cur_sc, $this->registered_codes)) { if ($this->registered_codes[$cur_sc]['type'] == 'plugin') { $scFile = e_PLUGIN.strtolower($this->registered_codes[$cur_sc]['path']).'/'.strtolower($cur_sc).'.sc'; } else { $scFile = THEME.strtolower($cur_sc).'.sc'; } if (is_readable($scFile)) { $cur_shortcodes[$cur_sc] = file_get_contents($scFile); } } } return $cur_shortcodes; } } class e_shortcode { /** * Stores passed to shortcode handler array data * Usage: $this->var['someKey'] * Assigned via setVars() and addVars() methods * @var array */ protected $var = array(); // value available to each shortcode. protected $mode = 'view'; // or edit. Used within shortcodes for form elements vs values only. protected $wrapper = null; // holds template/key value of the currently used wrapper (if any) - see contact_template.php for an example. protected $override = false; /** * Storage for shortcode values * @var e_vars */ protected $scVars = null; /** * e_shortcode constructor. */ public function __construct() { $this->scVars = new e_vars(); } /** * Startup code for child class */ public function init() {} /** * Sets wrapper id (to be retrieved from the registry while parsing) * Example e107::getScBatch('contact')->wrapper('contact/form'); * which results in using the $CONTACT_WRAPPER['form'] wrapper in the parsing phase * Template cannot be loaded via include, only by getTemplate or getCoreTemplate * e107::getScBatch() must be used also. */ public function wrapper($id = null) { if(null === $id) return $this->wrapper; if(false === $id) $id = null; $this->wrapper = $id; return $this; } public function getWrapperID() { return $this->wrapper; } /** * Set external array data to be used in the batch * Use setVars() - preferred. * //XXX will soon become private. Use setVars() instead. * @param array $eVars * @return e_shortcode */ public function setParserVars($eVars) { $this->var = $eVars; return $this; } /** * Alias of setParserVars - Preferred use by Plugins. * Sets the value of $sc->var */ public function setVars($eVars) // Alias of setParserVars(); { return $this->setParserVars($eVars); } /** * Add array to current parser array data * @param array $array * @return e_shortcode */ public function addParserVars($array) { if(!is_array($array)) return $this; $this->var = array_merge($this->var, $array); return $this; } /** * Alias of addParserVars() * @param array $array * @return e_shortcode */ public function addVars($array) { return $this->addParserVars($array); } /** * Get external simple parser object * * @return array */ public function getParserVars() { return $this->var; } /** * Alias of getParserVars() * * @return array */ public function getVars() { return $this->getParserVars(); } /** * Batch mod * @param string mod * @return e_shortcode */ public function setMode($mode) { $this->mode = ($mode == 'edit') ? 'edit' : 'view'; return $this; } /** * Add shortcode value *
$'.$wrapActive.'[\'SHORTCODE_NAME\'] = "(html before){---}(html after)";
e107::getScBatch('class_name')->setScVar('some_property', $some_value);
*
* @param string $name
* @param mixed $value
* @return e_shortcode
*/
public function setScVar($name, $value)
{
$this->scVars->$name = $value;
return $this;
}
/**
* Add shortcode values
* e107::getScBatch('class_name')->addScVars(array('some_property', $some_value));
*
* @param array $vars
* @return e_shortcode
*/
public function addScVars($vars)
{
$this->scVars->addVars($vars);
return $this;
}
/**
* Retrieve shortcode value
* $some_value = e107::getScBatch('class_name')->getScVar('some_property');
*
* @param string $name
* @return mixed
*/
public function getScVar($name)
{
return $this->scVars->$name;
}
/**
* Retrieve all shortcode values
* $some_value = e107::getScBatch('class_name')->getScVars();
*
* @return mixed
*/
public function getScVars()
{
return $this->scVars->getVars();
}
/**
* Check if shortcode variable is set
* if(e107::getScBatch('class_name')->issetScVar('some_property'))
* {
* //do something
* }
*
* @param string $name
* @return boolean
*/
public function issetScVar($name)
{
return isset($this->scVars->$name);
}
/**
* Unset shortcode value
* e107::getScBatch('class_name')->unsetScVar('some_property');
*
* @param string $name
* @return e_shortcode
*/
public function unsetScVar($name)
{
$this->scVars->$name = null;
unset($this->scVars->$name);
return $this;
}
/**
* Empty scvar object data
* @return e_shortcode
*/
public function emptyScVars()
{
$this->scVars->emptyVars();
return $this;
}
/**
* Magic setter - bind to eVars object
*
* @param string $name
* @param mixed $value
*/
public function __set($name, $value)
{
$this->setScVar($name, $value);
}
/**
* Magic getter - bind to eVars object
*
* @param string $name
* @return mixed value or null if key not found
*/
public function __get($name)
{
return $this->getScVar($name);
}
/**
* Magic method - bind to eVars object
* NOTE: works on PHP 5.1.0+
*
* @param string $name
* @return boolean
*/
public function __isset($name)
{
return $this->issetScVar($name);
}
/**
* Magic method - bind to eVars object
* NOTE: works on PHP 5.1.0+
*
* @param string $name
*/
public function __unset($name)
{
$this->unsetScVar($name);
}
}