_snippets[3]['type'] = 'template';
*/
var $_snippets;
/**
* Whether the snippets array has been sorted
*
* @var boolean
*/
var $_isSorted;
/**
* @param string $name
*/
public function __construct($name) {
// Templates injected into regions should normally be file names, but sometimes inline notation is handy.
require_once 'CRM/Core/Smarty/resources/String.php';
civicrm_smarty_register_string_resource();
$this->_name = $name;
$this->_snippets = array();
// Placeholder which represents any of the default content generated by the main Smarty template
$this->add(array(
'name' => 'default',
'type' => 'markup',
'markup' => '',
'weight' => 0,
));
$this->_isSorted = TRUE;
}
/**
* Add a snippet of content to a region.
*
* @code
* CRM_Core_Region::instance('page-header')->add(array(
* 'markup' => '
Hello!
',
* ));
* CRM_Core_Region::instance('page-header')->add(array(
* 'script' => 'alert("Hello");',
* ));
* CRM_Core_Region::instance('page-header')->add(array(
* 'template' => 'CRM/Myextension/Extra.tpl',
* ));
* CRM_Core_Region::instance('page-header')->add(array(
* 'callback' => 'myextension_callback_function',
* ));
* @endcode
*
* Note: This function does not perform any extra encoding of markup, script code, or etc. If
* you're passing in user-data, you must clean it yourself.
*
* @param array $snippet
* Array; keys:.
* - type: string (auto-detected for markup, template, callback, script, scriptUrl, jquery, style, styleUrl)
* - name: string, optional
* - weight: int, optional; default=1
* - disabled: int, optional; default=0
* - markup: string, HTML; required (for type==markup)
* - template: string, path; required (for type==template)
* - callback: mixed; required (for type==callback)
* - arguments: array, optional (for type==callback)
* - script: string, Javascript code
* - scriptUrl: string, URL of a Javascript file
* - jquery: string, Javascript code which runs inside a jQuery(function($){...}); block
* - style: string, CSS code
* - styleUrl: string, URL of a CSS file
*
* @return array
*/
public function add($snippet) {
static $types = array('markup', 'template', 'callback', 'scriptUrl', 'script', 'jquery', 'style', 'styleUrl');
$defaults = array(
'region' => $this->_name,
'weight' => 1,
'disabled' => FALSE,
);
$snippet += $defaults;
if (!isset($snippet['type'])) {
foreach ($types as $type) {
// auto-detect
if (isset($snippet[$type])) {
$snippet['type'] = $type;
break;
}
}
}
if (!isset($snippet['name'])) {
$snippet['name'] = count($this->_snippets);
}
$this->_snippets[$snippet['name']] = $snippet;
$this->_isSorted = FALSE;
return $snippet;
}
/**
* @param string $name
* @param $snippet
*/
public function update($name, $snippet) {
$this->_snippets[$name] = array_merge($this->_snippets[$name], $snippet);
$this->_isSorted = FALSE;
}
/**
* Get snippet.
*
* @param string $name
*
* @return mixed
*/
public function get($name) {
return !empty($this->_snippets[$name]) ? $this->_snippets[$name] : NULL;
}
/**
* Render all the snippets in a region.
*
* @param string $default
* HTML, the initial content of the region.
* @param bool $allowCmsOverride
* Allow CMS to override rendering of region.
* @return string, HTML
*/
public function render($default, $allowCmsOverride = TRUE) {
// $default is just another part of the region
if (is_array($this->_snippets['default'])) {
$this->_snippets['default']['markup'] = $default;
}
// We hand as much of the work off to the CMS as possible
$cms = CRM_Core_Config::singleton()->userSystem;
if (!$this->_isSorted) {
uasort($this->_snippets, array('CRM_Core_Region', '_cmpSnippet'));
$this->_isSorted = TRUE;
}
$smarty = CRM_Core_Smarty::singleton();
$html = '';
foreach ($this->_snippets as $snippet) {
if ($snippet['disabled']) {
continue;
}
switch ($snippet['type']) {
case 'markup':
$html .= $snippet['markup'];
break;
case 'template':
$tmp = $smarty->get_template_vars('snippet');
$smarty->assign('snippet', $snippet);
$html .= $smarty->fetch($snippet['template']);
$smarty->assign('snippet', $tmp);
break;
case 'callback':
$args = isset($snippet['arguments']) ? $snippet['arguments'] : array(&$snippet, &$html);
$html .= call_user_func_array($snippet['callback'], $args);
break;
case 'scriptUrl':
if (!$allowCmsOverride || !$cms->addScriptUrl($snippet['scriptUrl'], $this->_name)) {
$html .= sprintf("\n", $snippet['scriptUrl']);
}
break;
case 'jquery':
$snippet['script'] = sprintf("CRM.\$(function(\$) {\n%s\n});", $snippet['jquery']);
// no break - continue processing as script
case 'script':
if (!$allowCmsOverride || !$cms->addScript($snippet['script'], $this->_name)) {
$html .= sprintf("\n", $snippet['script']);
}
break;
case 'styleUrl':
if (!$allowCmsOverride || !$cms->addStyleUrl($snippet['styleUrl'], $this->_name)) {
$html .= sprintf("\n", $snippet['styleUrl']);
}
break;
case 'style':
if (!$allowCmsOverride || !$cms->addStyle($snippet['style'], $this->_name)) {
$html .= sprintf("\n", $snippet['style']);
}
break;
default:
require_once 'CRM/Core/Error.php';
CRM_Core_Error::fatal(ts('Snippet type %1 is unrecognized',
array(1 => $snippet['type'])));
}
}
return $html;
}
/**
* @param $a
* @param $b
*
* @return int
*/
public static function _cmpSnippet($a, $b) {
if ($a['weight'] < $b['weight']) {
return -1;
}
if ($a['weight'] > $b['weight']) {
return 1;
}
// fallback to name sort; don't really want to do this, but it makes results more stable
if ($a['name'] < $b['name']) {
return -1;
}
if ($a['name'] > $b['name']) {
return 1;
}
return 0;
}
/**
* Add block of static HTML to a region.
*
* @param string $markup
* HTML.
*
* public function addMarkup($markup) {
* return $this->add(array(
* 'type' => 'markup',
* 'markup' => $markup,
* ));
* }
*
* /**
* Add a Smarty template file to a region.
*
* Note: File is not evaluated until the page is rendered
*
* @param string $template
* Path to the Smarty template file.
*
* public function addTemplate($template) {
* return $this->add(array(
* 'type' => 'template',
* 'template' => $template,
* ));
* }
*
* /**
* Use a callback function to extend a region.
*
* @param mixed $callback
* @param array $arguments
* Optional, array of parameters for callback; if omitted, the default arguments are ($snippetSpec, $html).
*
* public function addCallback($callback, $arguments = FALSE) {
* return $this->add(array(
* 'type' => 'callback',
* 'callback' => $callback,
* 'arguments' => $arguments,
* ));
* }
*/
}