PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/system/advancedmodules/modulehelper.php

https://bitbucket.org/organicdevelopment/joomla-2.5
PHP | 629 lines | 369 code | 85 blank | 175 comment | 59 complexity | aad908f795b18d92c9210a36e9f19fa7 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-2.0, MIT, BSD-3-Clause, LGPL-2.1
  1. <?php
  2. /**
  3. * @package Advanced Module Manager
  4. * @version 3.2.6
  5. *
  6. * @author Peter van Westen <peter@nonumber.nl>
  7. * @link http://www.nonumber.nl
  8. * @copyright Copyright Š 2011 All Rights Reserved
  9. * Brandon IT Consulting (http://www.metamodpro.com)
  10. * NoNumber (http://www.nonumber.nl)
  11. * JoomlArt (http://www.joomlart.com)
  12. * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
  13. */
  14. /**
  15. * BASE ON JOOMLA CORE FILE:
  16. * /libraries/joomla/application/module/helper.php
  17. */
  18. /**
  19. * @package Joomla.Platform
  20. * @subpackage Application
  21. *
  22. * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
  23. * @license GNU General Public License version 2 or later; see LICENSE
  24. */
  25. defined('JPATH_PLATFORM') or defined('JPATH_BASE') or die;
  26. jimport('joomla.application.component.helper');
  27. /**
  28. * Module helper class
  29. *
  30. * @package Joomla.Platform
  31. * @subpackage Application
  32. * @since 11.1
  33. */
  34. abstract class JModuleHelper
  35. {
  36. /**
  37. * Get module by name (real, eg 'Breadcrumbs' or folder, eg 'mod_breadcrumbs')
  38. *
  39. * @param string $name The name of the module
  40. * @param string $title The title of the module, optional
  41. *
  42. * @return object The Module object
  43. *
  44. * @since 11.1
  45. */
  46. public static function &getModule($name, $title = null)
  47. {
  48. $result = null;
  49. $modules =& JModuleHelper::_load();
  50. $total = count($modules);
  51. for ($i = 0; $i < $total; $i++)
  52. {
  53. // Match the name of the module
  54. if ($modules[$i]->name == $name || $modules[$i]->module == $name)
  55. {
  56. // Match the title if we're looking for a specific instance of the module
  57. if (!$title || $modules[$i]->title == $title)
  58. {
  59. // Found it
  60. $result = &$modules[$i];
  61. break; // Found it
  62. }
  63. }
  64. }
  65. // If we didn't find it, and the name is mod_something, create a dummy object
  66. if (is_null($result) && substr($name, 0, 4) == 'mod_')
  67. {
  68. $result = new stdClass;
  69. $result->id = 0;
  70. $result->title = '';
  71. $result->module = $name;
  72. $result->position = '';
  73. $result->content = '';
  74. $result->showtitle = 0;
  75. $result->control = '';
  76. $result->params = '';
  77. $result->user = 0;
  78. }
  79. return $result;
  80. }
  81. /**
  82. * Get modules by position
  83. *
  84. * @param string $position The position of the module
  85. *
  86. * @return array An array of module objects
  87. *
  88. * @since 11.1
  89. */
  90. public static function &getModules($position)
  91. {
  92. $position = strtolower($position);
  93. $result = array();
  94. $modules =& JModuleHelper::_load();
  95. $total = count($modules);
  96. for ($i = 0; $i < $total; $i++)
  97. {
  98. if ($modules[$i]->position == $position)
  99. {
  100. $result[] = &$modules[$i];
  101. }
  102. }
  103. if (count($result) == 0)
  104. {
  105. if (JRequest::getBool('tp') && JComponentHelper::getParams('com_templates')->get('template_positions_display'))
  106. {
  107. $result[0] = JModuleHelper::getModule('mod_' . $position);
  108. $result[0]->title = $position;
  109. $result[0]->content = $position;
  110. $result[0]->position = $position;
  111. }
  112. }
  113. return $result;
  114. }
  115. /**
  116. * Checks if a module is enabled
  117. *
  118. * @param string $module The module name
  119. *
  120. * @return boolean
  121. *
  122. * @since 11.1
  123. */
  124. public static function isEnabled($module)
  125. {
  126. $result = JModuleHelper::getModule($module);
  127. return !is_null($result);
  128. }
  129. /**
  130. * Render the module.
  131. *
  132. * @param object $module A module object.
  133. * @param array $attribs An array of attributes for the module (probably from the XML).
  134. *
  135. * @return string The HTML content of the module output.
  136. *
  137. * @since 11.1
  138. */
  139. public static function renderModule($module, $attribs = array())
  140. {
  141. static $chrome;
  142. if (constant('JDEBUG'))
  143. {
  144. JProfiler::getInstance('Application')->mark('beforeRenderModule ' . $module->module . ' (' . $module->title . ')');
  145. }
  146. $app = JFactory::getApplication();
  147. // Record the scope.
  148. $scope = $app->scope;
  149. // Set scope to component name
  150. $app->scope = $module->module;
  151. // Get module parameters
  152. $params = new JRegistry;
  153. $params->loadString($module->params);
  154. // Get module path
  155. $module->module = preg_replace('/[^A-Z0-9_\.-]/i', '', $module->module);
  156. $path = JPATH_BASE . '/modules/' . $module->module . '/' . $module->module . '.php';
  157. // Load the module
  158. // $module->user is a check for 1.0 custom modules and is deprecated refactoring
  159. if (empty($module->user) && file_exists($path))
  160. {
  161. $lang = JFactory::getLanguage();
  162. // 1.5 or Core then 1.6 3PD
  163. $lang->load($module->module, JPATH_BASE, null, false, false) ||
  164. $lang->load($module->module, dirname($path), null, false, false) ||
  165. $lang->load($module->module, JPATH_BASE, $lang->getDefault(), false, false) ||
  166. $lang->load($module->module, dirname($path), $lang->getDefault(), false, false);
  167. $content = '';
  168. ob_start();
  169. include $path;
  170. $module->content = ob_get_contents() . $content;
  171. ob_end_clean();
  172. }
  173. // Load the module chrome functions
  174. if (!$chrome)
  175. {
  176. $chrome = array();
  177. }
  178. include_once JPATH_THEMES . '/system/html/modules.php';
  179. $chromePath = JPATH_THEMES . '/' . $app->getTemplate() . '/html/modules.php';
  180. if (!isset($chrome[$chromePath]))
  181. {
  182. if (file_exists($chromePath))
  183. {
  184. include_once $chromePath;
  185. }
  186. $chrome[$chromePath] = true;
  187. }
  188. // Make sure a style is set
  189. if (!isset($attribs['style']))
  190. {
  191. $attribs['style'] = 'none';
  192. }
  193. // Dynamically add outline style
  194. if (JRequest::getBool('tp') && JComponentHelper::getParams('com_templates')->get('template_positions_display'))
  195. {
  196. $attribs['style'] .= ' outline';
  197. }
  198. // Do 3rd party stuff to manipulate module content
  199. // onRenderModule is allowed to alter the $module, $attribs
  200. // and may return a boolean.
  201. // true=remove, any other value = keep.
  202. // $result holds an array of booleans, 1 from each plugin.
  203. // we ditch the module if any of them = true.
  204. $result = $app->triggerEvent( 'onRenderModule', array( &$module, &$attribs ) );
  205. if ( array_search( true, $result, true ) !== false )
  206. {
  207. return '';
  208. }
  209. foreach (explode(' ', $attribs['style']) as $style)
  210. {
  211. $chromeMethod = 'modChrome_' . $style;
  212. // Apply chrome and render module
  213. if (function_exists($chromeMethod))
  214. {
  215. $module->style = $attribs['style'];
  216. ob_start();
  217. $chromeMethod($module, $params, $attribs);
  218. $module->content = ob_get_contents();
  219. ob_end_clean();
  220. }
  221. }
  222. //revert the scope
  223. $app->scope = $scope;
  224. if (constant('JDEBUG'))
  225. {
  226. JProfiler::getInstance('Application')->mark('afterRenderModule ' . $module->module . ' (' . $module->title . ')');
  227. }
  228. return $module->content;
  229. }
  230. /**
  231. * Get the path to a layout for a module
  232. *
  233. * @param string $module The name of the module
  234. * @param string $layout The name of the module layout. If alternative layout, in the form template:filename.
  235. *
  236. * @return string The path to the module layout
  237. *
  238. * @since 11.1
  239. */
  240. public static function getLayoutPath($module, $layout = 'default')
  241. {
  242. $template = JFactory::getApplication()->getTemplate();
  243. $defaultLayout = $layout;
  244. if (strpos($layout, ':') !== false)
  245. {
  246. // Get the template and file name from the string
  247. $temp = explode(':', $layout);
  248. $template = ($temp[0] == '_') ? $template : $temp[0];
  249. $layout = $temp[1];
  250. $defaultLayout = ($temp[1]) ? $temp[1] : 'default';
  251. }
  252. // Build the template and base path for the layout
  253. $tPath = JPATH_THEMES . '/' . $template . '/html/' . $module . '/' . $layout . '.php';
  254. $bPath = JPATH_BASE . '/modules/' . $module . '/tmpl/' . $defaultLayout . '.php';
  255. $dPath = JPATH_BASE . '/modules/' . $module . '/tmpl/default.php';
  256. // Do 3rd party stuff to detect layout path for the module
  257. // onGetLayoutPath should return the path to the $layout of $module or false
  258. // $results holds an array of results returned from plugins, 1 from each plugin.
  259. // if a path to the $layout is found and it is a file, return that path
  260. $app = JFactory::getApplication();
  261. $result = $app->triggerEvent( 'onGetLayoutPath', array( $module, $layout ) );
  262. if (is_array($result))
  263. {
  264. foreach ($result as $path)
  265. {
  266. if ($path !== false && is_file ($path))
  267. {
  268. return $path;
  269. }
  270. }
  271. }
  272. // If the template has a layout override use it
  273. if (file_exists($tPath))
  274. {
  275. return $tPath;
  276. }
  277. elseif (file_exists($bPath))
  278. {
  279. return $bPath;
  280. }
  281. else
  282. {
  283. return $dPath;
  284. }
  285. }
  286. /**
  287. * Load published modules.
  288. *
  289. * @return array
  290. *
  291. * @since 11.1
  292. */
  293. protected static function &_load()
  294. {
  295. static $clean;
  296. if (isset($clean))
  297. {
  298. return $clean;
  299. }
  300. $Itemid = JRequest::getInt('Itemid');
  301. $app = JFactory::getApplication();
  302. $user = JFactory::getUser();
  303. $groups = implode(',', $user->getAuthorisedViewLevels());
  304. $lang = JFactory::getLanguage()->getTag();
  305. $clientId = (int) $app->getClientId();
  306. /*
  307. $cache = JFactory::getCache('com_modules', '');
  308. $cacheid = md5(serialize(array($Itemid, $groups, $clientId, $lang)));
  309. if (!($clean = $cache->get($cacheid)))
  310. {
  311. */
  312. $db = JFactory::getDbo();
  313. $query = new stdClass();
  314. $query->select = array();
  315. $query->from = array();
  316. $query->join = array();
  317. $query->where = array();
  318. $query->order = array();
  319. $query->select[] = 'm.published, m.id, m.title, m.module, m.position, m.content, m.showtitle, m.params, mm.menuid';
  320. $query->from[] = '#__modules AS m';
  321. $query->join[] = '#__modules_menu AS mm ON mm.moduleid = m.id';
  322. $query->where[] = 'm.published = 1';
  323. $query->join[] = '#__extensions AS e ON e.element = m.module AND e.client_id = m.client_id';
  324. $query->where[] = 'e.enabled = 1';
  325. $date = JFactory::getDate();
  326. $now = $date->toSql();
  327. $nullDate = $db->getNullDate();
  328. $query->where[] = '(m.publish_up = ' . $db->q($nullDate) . ' OR m.publish_up <= ' . $db->q($now) . ')';
  329. $query->where[] = '(m.publish_down = ' . $db->q($nullDate) . ' OR m.publish_down >= ' . $db->q($now) . ')';
  330. $query->where[] = 'm.access IN ('.$groups.')';
  331. $query->where[] = 'm.client_id = ' . $clientId;
  332. $query->where[] = '(mm.menuid = ' . (int) $Itemid . ' OR mm.menuid <= 0)';
  333. // Filter by language
  334. if ($app->isSite() && $app->getLanguageFilter())
  335. {
  336. $query->where[] = 'm.language IN (' . $db->q($lang) . ',' . $db->q('*') . ')';
  337. }
  338. $query->order[] = 'm.position, m.ordering';
  339. // Do 3rd party stuff to change query
  340. $app->triggerEvent( 'onCreateModuleQuery', array( &$query ) );
  341. $q = $db->getQuery(true);
  342. // convert array object to query object
  343. foreach ( $query as $type => $strings )
  344. {
  345. foreach ( $strings as $string )
  346. {
  347. if ( $type == 'join' )
  348. {
  349. $q->{$type}( 'LEFT', $string );
  350. }
  351. else
  352. {
  353. $q->{$type}( $string );
  354. }
  355. }
  356. }
  357. // Set the query
  358. $db->setQuery($q);
  359. $modules = $db->loadObjectList();
  360. $clean = array();
  361. if ($db->getErrorNum())
  362. {
  363. JError::raiseWarning(500, JText::sprintf('JLIB_APPLICATION_ERROR_MODULE_LOAD', $db->getErrorMsg()));
  364. return $clean;
  365. }
  366. // Apply negative selections and eliminate duplicates
  367. $negId = $Itemid ? -(int) $Itemid : false;
  368. $dupes = array();
  369. for ($i = 0, $n = count($modules); $i < $n; $i++)
  370. {
  371. $module = &$modules[$i];
  372. // The module is excluded if there is an explicit prohibition
  373. $negHit = ($negId === (int) $module->menuid);
  374. if (isset($dupes[$module->id]))
  375. {
  376. // If this item has been excluded, keep the duplicate flag set,
  377. // but remove any item from the cleaned array.
  378. if ($negHit)
  379. {
  380. unset($clean[$module->id]);
  381. }
  382. continue;
  383. }
  384. $dupes[$module->id] = true;
  385. // Only accept modules without explicit exclusions.
  386. if (!$negHit)
  387. {
  388. // Determine if this is a 1.0 style custom module (no mod_ prefix)
  389. // This should be eliminated when the class is refactored.
  390. // $module->user is deprecated.
  391. $file = $module->module;
  392. $custom = substr($file, 0, 4) == 'mod_' ? 0 : 1;
  393. $module->user = $custom;
  394. // 1.0 style custom module name is given by the title field, otherwise strip off "mod_"
  395. $module->name = $custom ? $module->module : substr($file, 4);
  396. $module->style = null;
  397. $module->position = strtolower($module->position);
  398. $clean[$module->id] = $module;
  399. }
  400. }
  401. unset($dupes);
  402. // Do 3rd party stuff to manipulate module array.
  403. // Any plugins using this architecture may make alterations to the referenced $modules array.
  404. // To remove items you can do unset($modules[n]) or $modules[n]->published = false.
  405. // "onPrepareModuleList" may alter or add $modules, and does not need to return anything.
  406. // This should be used for module addition/deletion that the user would expect to happen at an
  407. // early stage.
  408. $app->triggerEvent( 'onPrepareModuleList', array( &$clean ) );
  409. // "onAlterModuleList" may alter or add $modules, and does not need to return anything.
  410. $app->triggerEvent( 'onAlterModuleList', array( &$clean ) );
  411. // "onPostProcessModuleList" allows a plugin to perform actions like parameter changes
  412. // on the completed list of modules and is guaranteed to occur *after*
  413. // the earlier plugins.
  414. $app->triggerEvent( 'onPostProcessModuleList', array( &$clean ) );
  415. // Remove any that were marked as disabled during the preceding steps
  416. foreach ( $clean as $id => $module )
  417. {
  418. if ( !isset( $module->published ) || $module->published == 0 )
  419. {
  420. unset( $clean[$id] );
  421. }
  422. }
  423. // Return to simple indexing that matches the query order.
  424. $clean = array_values($clean);
  425. /*
  426. $cache->store($clean, $cacheid);
  427. }
  428. */
  429. return $clean;
  430. }
  431. /**
  432. * Module cache helper
  433. *
  434. * Caching modes:
  435. * To be set in XML:
  436. * 'static' One cache file for all pages with the same module parameters
  437. * 'oldstatic' 1.5 definition of module caching, one cache file for all pages
  438. * with the same module id and user aid,
  439. * 'itemid' Changes on itemid change, to be called from inside the module:
  440. * 'safeuri' Id created from $cacheparams->modeparams array,
  441. * 'id' Module sets own cache id's
  442. *
  443. * @param object $module Module object
  444. * @param object $moduleparams Module parameters
  445. * @param object $cacheparams Module cache parameters - id or url parameters, depending on the module cache mode
  446. *
  447. * @return string
  448. *
  449. * @since 11.1
  450. *
  451. * @link JFilterInput::clean()
  452. */
  453. public static function moduleCache($module, $moduleparams, $cacheparams)
  454. {
  455. if (!isset($cacheparams->modeparams))
  456. {
  457. $cacheparams->modeparams = null;
  458. }
  459. if (!isset($cacheparams->cachegroup))
  460. {
  461. $cacheparams->cachegroup = $module->module;
  462. }
  463. $user = JFactory::getUser();
  464. $cache = JFactory::getCache($cacheparams->cachegroup, 'callback');
  465. $conf = JFactory::getConfig();
  466. // Turn cache off for internal callers if parameters are set to off and for all logged in users
  467. if ($moduleparams->get('owncache', null) === '0' || $conf->get('caching') == 0 || $user->get('id'))
  468. {
  469. $cache->setCaching(false);
  470. }
  471. // module cache is set in seconds, global cache in minutes, setLifeTime works in minutes
  472. $cache->setLifeTime($moduleparams->get('cache_time', $conf->get('cachetime') * 60) / 60);
  473. $wrkaroundoptions = array('nopathway' => 1, 'nohead' => 0, 'nomodules' => 1, 'modulemode' => 1, 'mergehead' => 1);
  474. $wrkarounds = true;
  475. $view_levels = md5(serialize($user->getAuthorisedViewLevels()));
  476. switch ($cacheparams->cachemode)
  477. {
  478. case 'id':
  479. $ret = $cache->get(
  480. array($cacheparams->class, $cacheparams->method),
  481. $cacheparams->methodparams,
  482. $cacheparams->modeparams,
  483. $wrkarounds,
  484. $wrkaroundoptions
  485. );
  486. break;
  487. case 'safeuri':
  488. $secureid = null;
  489. if (is_array($cacheparams->modeparams))
  490. {
  491. $uri = JRequest::get();
  492. $safeuri = new stdClass;
  493. foreach ($cacheparams->modeparams as $key => $value)
  494. {
  495. // Use int filter for id/catid to clean out spamy slugs
  496. if (isset($uri[$key]))
  497. {
  498. $safeuri->$key = JRequest::_cleanVar($uri[$key], 0, $value);
  499. }
  500. }
  501. }
  502. $secureid = md5(serialize(array($safeuri, $cacheparams->method, $moduleparams)));
  503. $ret = $cache->get(
  504. array($cacheparams->class, $cacheparams->method),
  505. $cacheparams->methodparams,
  506. $module->id . $view_levels . $secureid,
  507. $wrkarounds,
  508. $wrkaroundoptions
  509. );
  510. break;
  511. case 'static':
  512. $ret = $cache->get(
  513. array($cacheparams->class,
  514. $cacheparams->method),
  515. $cacheparams->methodparams,
  516. $module->module . md5(serialize($cacheparams->methodparams)),
  517. $wrkarounds,
  518. $wrkaroundoptions
  519. );
  520. break;
  521. case 'oldstatic': // provided for backward compatibility, not really usefull
  522. $ret = $cache->get(
  523. array($cacheparams->class, $cacheparams->method),
  524. $cacheparams->methodparams,
  525. $module->id . $view_levels,
  526. $wrkarounds,
  527. $wrkaroundoptions
  528. );
  529. break;
  530. case 'itemid':
  531. default:
  532. $ret = $cache->get(
  533. array($cacheparams->class, $cacheparams->method),
  534. $cacheparams->methodparams,
  535. $module->id . $view_levels . JRequest::getVar('Itemid', null, 'default', 'INT'),
  536. $wrkarounds,
  537. $wrkaroundoptions
  538. );
  539. break;
  540. }
  541. return $ret;
  542. }
  543. }