<?php
/**
* [PHPFOX_HEADER]
*/
defined('PHPFOX') or exit('NO DICE!');
/**
* Plugins
* Our product is built around a plug-in system that allows 3rd party
* code to easily hook onto our core library and other modules without
* the need to modify its code. This class takes care of creating the
* hook environment.
*
* @copyright [PHPFOX_COPYRIGHT]
* @author Raymond Benc
* @package Phpfox
* @version $Id: plugin.class.php 6599 2013-09-06 08:18:37Z Miguel_Espinoza $
*/
class Phpfox_Plugin
{
/**
* ARRAY of plug-ins to be used.
*
* @var array
*/
public static $_aPlugins = array();
public static function set()
{
$aPlugins = array();
$oCache = Phpfox::getLib('cache');
$iCacheId = $oCache->set(array('plugin', 'plugin'));
if ((Phpfox::getParam('core.cache_plugins') && (!(self::$_aPlugins = $oCache->get($iCacheId)))) || !Phpfox::getParam('core.cache_plugins'))
{
$oDb = Phpfox_Database::instance();
$aRows = $oDb->select('p.call_name, p.php_code')
->from(Phpfox::getT('plugin'), 'p')
->join(Phpfox::getT('product'), 'product', 'p.product_id = product.product_id AND product.is_active = 1')
->join(Phpfox::getT('plugin_hook'), 'ph', 'ph.call_name = p.call_name AND ph.is_active = 1')
->join(Phpfox::getT('module'), 'm', 'm.module_id = p.module_id AND m.is_active = 1')
->where('p.is_active = 1')
->order('p.ordering ASC')
->execute('getRows');
$oDb->freeResult();
foreach ($aRows as $aRow)
{
$aRow['call_name'] = strtolower($aRow['call_name']);
if (isset($aPlugins[$aRow['call_name']]))
{
$aPlugins[$aRow['call_name']] .= self::_cleanPhp($aRow['php_code']) . " ";
}
else
{
$aPlugins[$aRow['call_name']] = self::_cleanPhp($aRow['php_code']) . " ";
}
}
foreach ((new Core\App())->all() as $app) {
if (isset($app->webhooks)) {
foreach ($app->webhooks as $hook => $url) {
if (preg_match('/plugin:(.*)/i', $hook, $matches) && isset($matches[1])) {
$name = $matches[1];
$code = "(new \\Core\\Webhook('{$hook}', '{$url}'));";
if (isset($aPlugins[$name]))
{
$aPlugins[$name] .= $code . " ";
}
else
{
$aPlugins[$name] = $code . " ";
}
}
}
}
$dir = $app->path . 'hooks/';
if (is_dir($dir)) {
foreach (scandir($dir) as $file) {
if (substr($file, -4) == '.php') {
$code = self::_cleanPhp(file_get_contents($dir . $file));
$name = substr_replace($file, '', -4);
if (isset($aPlugins[$name]))
{
$aPlugins[$name] .= $code . " ";
}
else
{
$aPlugins[$name] = $code . " ";
}
}
}
}
}
$aModules = Phpfox_Module::instance()->getModules();
foreach ($aModules as $sModule => $iModuleId)
{
if (is_dir(PHPFOX_DIR_MODULE . $sModule . PHPFOX_DS . PHPFOX_DIR_MODULE_PLUGIN . PHPFOX_DS))
{
if (!Phpfox::isModule($sModule))
{
continue;
}
$rHooks = opendir(PHPFOX_DIR_MODULE . $sModule . PHPFOX_DS . PHPFOX_DIR_MODULE_PLUGIN . PHPFOX_DS);
while (($sHook = readdir($rHooks)) !== false)
{
if (substr($sHook, -4) != '.php')
{
continue;
}
$sHookContent = self::_cleanPhp(file_get_contents(PHPFOX_DIR_MODULE . $sModule . PHPFOX_DS . PHPFOX_DIR_MODULE_PLUGIN . PHPFOX_DS . $sHook));
$sHookVarName = substr_replace($sHook, '', -4);
if (isset($aPlugins[$sHookVarName]))
{
$aPlugins[$sHookVarName] .= $sHookContent . " ";
}
else
{
$aPlugins[$sHookVarName] = $sHookContent . " ";
}
}
closedir($rHooks);
}
}
$hPlugin = opendir(PHPFOX_DIR_PLUGIN);
while ($sProduct = readdir($hPlugin))
{
if ($sProduct == '.' || $sProduct == '..')
{
continue;
}
if (is_dir(PHPFOX_DIR_PLUGIN . $sProduct))
{
if (!Admincp_Service_Product_Product::instance()->isProduct($sProduct))
{
continue;
}
$hProduct = opendir(PHPFOX_DIR_PLUGIN . $sProduct);
while ($sHook = readdir($hProduct))
{
if (substr($sHook, -4) != '.php')
{
continue;
}
$sHookContent = self::_cleanPhp(file_get_contents(PHPFOX_DIR_PLUGIN . $sProduct . PHPFOX_DS . $sHook));
$sHookVarName = substr_replace($sHook, '', -4);
if (isset($aPlugins[$sHookVarName]))
{
$aPlugins[$sHookVarName] .= $sHookContent . " ";
}
else
{
$aPlugins[$sHookVarName] = $sHookContent . " ";
}
}
closedir($hProduct);
}
}
foreach (array_keys($aPlugins) as $sKey)
{
self::$_aPlugins[$sKey] = $sKey;
$iPluginCacheId = $oCache->set(array('plugin', 'plugin_data_' . $sKey));
if ((Phpfox::getParam('core.cache_plugins') && (!$oCache->get($iPluginCacheId))) || !Phpfox::getParam('core.cache_plugins'))
{
$oCache->save($iPluginCacheId, $aPlugins[$sKey]);
}
$oCache->close($iPluginCacheId);
}
$oCache->save($iCacheId, self::$_aPlugins);
}
User_Service_Group_Setting_Setting::instance()->loadAlias();
}
/**
* Get a specific plug-in.
*
* @param string $sCallName Name of the plug-in.
* @return mixed FALSE if we cannot find a plug-in, PHP code if we can which will then later be evaled.
*/
public static function get($sCallName)
{
$sCallName = str_replace('::', '_', $sCallName);
$sCallName = strtolower($sCallName);
if (isset(self::$_aPlugins[$sCallName]))
{
$oCache = Phpfox::getLib('cache');
$iCacheId = $oCache->set(array('plugin', 'plugin_data_' . self::$_aPlugins[$sCallName]));
if (!($sPlugin = $oCache->get($iCacheId)))
{
// Do something, plug-in was not cached for some odd reason...
}
$oCache->close($iCacheId);
return $sPlugin;
}
return false;
}
/**
* Clean out any PHP that is causing problems when we eval the code.
*
* @param string $sHookContent PHP code to parse.
* @return string Fixed PHP code.
*/
private static function _cleanPhp($sHookContent)
{
$sHookContent = trim($sHookContent);
if (substr($sHookContent, 0, 5) == '<?php')
{
$sHookContent = substr_replace($sHookContent, '', 0, 5);
}
if (substr($sHookContent, 0, 2) == '<?')
{
$sHookContent = substr_replace($sHookContent, '', 0, 2);
}
if (substr($sHookContent, -2) == '?>')
{
$sHookContent = substr_replace($sHookContent, '', -2);
}
$sHookContent = trim($sHookContent);
return $sHookContent;
}
}