mirror of
https://github.com/getgrav/grav.git
synced 2026-05-07 10:46:54 +02:00
Add new ContentBlock classes
This commit is contained in:
229
system/src/Grav/Framework/ContentBlock/ContentBlock.php
Normal file
229
system/src/Grav/Framework/ContentBlock/ContentBlock.php
Normal file
@@ -0,0 +1,229 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\ContentBlock
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 RocketTheme, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\ContentBlock;
|
||||
|
||||
/**
|
||||
* Class to create nested blocks of content.
|
||||
*
|
||||
* $innerBlock = ContentBlock::create();
|
||||
* $innerBlock->setContent('my inner content');
|
||||
* $outerBlock = ContentBlock::create();
|
||||
* $outerBlock->setContent(sprintf('Inside my outer block I have %s.', $innerBlock->getToken()));
|
||||
* $outerBlock->addBlock($innerBlock);
|
||||
* echo $outerBlock;
|
||||
*
|
||||
* @package Grav\Framework\ContentBlock
|
||||
*/
|
||||
class ContentBlock implements ContentBlockInterface
|
||||
{
|
||||
protected $version = 1;
|
||||
protected $id;
|
||||
protected $tokenTemplate = '@@BLOCK-%s@@';
|
||||
protected $content = '';
|
||||
protected $blocks = [];
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
* @return static
|
||||
*/
|
||||
public static function create($id = null)
|
||||
{
|
||||
return new static($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $serialized
|
||||
* @return ContentBlockInterface
|
||||
*/
|
||||
public static function fromArray(array $serialized)
|
||||
{
|
||||
try {
|
||||
$type = isset($serialized['_type']) ? $serialized['_type'] : null;
|
||||
$id = isset($serialized['id']) ? $serialized['id'] : null;
|
||||
|
||||
if (!$type || !$id || !is_a($type, 'Grav\Framework\ContentBlock\ContentBlockInterface', true)) {
|
||||
throw new \RuntimeException('Bad data');
|
||||
}
|
||||
|
||||
/** @var ContentBlockInterface $instance */
|
||||
$instance = new $type($id);
|
||||
$instance->build($serialized);
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException(sprintf('Cannot unserialize Block: %s', $e->getMessage()), $e->getCode(), $e);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Block constructor.
|
||||
*
|
||||
* @param string $id
|
||||
*/
|
||||
public function __construct($id = null)
|
||||
{
|
||||
$this->id = $id ? (string) $id : $this->generateId();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getToken()
|
||||
{
|
||||
return sprintf($this->tokenTemplate, $this->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
$blocks = [];
|
||||
/**
|
||||
* @var string $id
|
||||
* @var ContentBlockInterface $block
|
||||
*/
|
||||
foreach ($this->blocks as $block) {
|
||||
$blocks[$block->getId()] = $block->toArray();
|
||||
}
|
||||
|
||||
$array = [
|
||||
'_type' => get_class($this),
|
||||
'_version' => $this->version,
|
||||
'id' => $this->id,
|
||||
];
|
||||
|
||||
if ($this->content) {
|
||||
$array['content'] = $this->content;
|
||||
}
|
||||
|
||||
if ($blocks) {
|
||||
$array['blocks'] = $blocks;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function toString()
|
||||
{
|
||||
if (!$this->blocks) {
|
||||
return (string) $this->content;
|
||||
}
|
||||
|
||||
$tokens = [];
|
||||
$replacements = [];
|
||||
foreach ($this->blocks as $block) {
|
||||
$tokens[] = $block->getToken();
|
||||
$replacements[] = $block->toString();
|
||||
}
|
||||
|
||||
return str_replace($tokens, $replacements, (string) $this->content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
try {
|
||||
return $this->toString();
|
||||
} catch (\Exception $e) {
|
||||
return sprintf('Error while rendering block: %s', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $serialized
|
||||
*/
|
||||
public function build(array $serialized)
|
||||
{
|
||||
$this->checkVersion($serialized);
|
||||
|
||||
$this->id = isset($serialized['id']) ? $serialized['id'] : $this->generateId();
|
||||
|
||||
if (isset($serialized['content'])) {
|
||||
$this->setContent($serialized['content']);
|
||||
}
|
||||
|
||||
$blocks = isset($serialized['blocks']) ? (array) $serialized['blocks'] : [];
|
||||
foreach ($blocks as $block) {
|
||||
$this->addBlock(self::fromArray($block));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return $this
|
||||
*/
|
||||
public function setContent($content)
|
||||
{
|
||||
$this->content = $content;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContentBlockInterface $block
|
||||
* @return $this
|
||||
*/
|
||||
public function addBlock(ContentBlockInterface $block)
|
||||
{
|
||||
$this->blocks[$block->getId()] = $block;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize($this->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $serialized
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
$array = unserialize($serialized);
|
||||
$this->build($array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function generateId()
|
||||
{
|
||||
return uniqid('', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $serialized
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function checkVersion(array $serialized)
|
||||
{
|
||||
$version = isset($serialized['_version']) ? (string) $serialized['_version'] : 1;
|
||||
if ($version != $this->version) {
|
||||
throw new \RuntimeException(sprintf('Unsupported version %s', $version));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\ContentBlock
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 RocketTheme, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\ContentBlock;
|
||||
|
||||
/**
|
||||
* ContentBlock Interface
|
||||
* @package Grav\Framework\ContentBlock
|
||||
*/
|
||||
interface ContentBlockInterface extends \Serializable
|
||||
{
|
||||
/**
|
||||
* @param string $id
|
||||
* @return static
|
||||
*/
|
||||
public static function create($id = null);
|
||||
|
||||
/**
|
||||
* @param array $serialized
|
||||
* @return ContentBlockInterface
|
||||
*/
|
||||
public static function fromArray(array $serialized);
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
*/
|
||||
public function __construct($id = null);
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getId();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getToken();
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function toString();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString();
|
||||
|
||||
/**
|
||||
* @param array $serialized
|
||||
*/
|
||||
public function build(array $serialized);
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @return $this
|
||||
*/
|
||||
public function setContent($content);
|
||||
|
||||
/**
|
||||
* @param ContentBlockInterface $block
|
||||
* @return $this
|
||||
*/
|
||||
public function addBlock(ContentBlockInterface $block);
|
||||
}
|
||||
374
system/src/Grav/Framework/ContentBlock/HtmlBlock.php
Normal file
374
system/src/Grav/Framework/ContentBlock/HtmlBlock.php
Normal file
@@ -0,0 +1,374 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\ContentBlock
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 RocketTheme, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\ContentBlock;
|
||||
|
||||
/**
|
||||
* HtmlBlock
|
||||
*
|
||||
* @package Grav\Framework\ContentBlock
|
||||
*/
|
||||
class HtmlBlock extends ContentBlock implements HtmlBlockInterface
|
||||
{
|
||||
protected $version = 1;
|
||||
protected $frameworks = [];
|
||||
protected $styles = [];
|
||||
protected $scripts = [];
|
||||
protected $html = [];
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAssets()
|
||||
{
|
||||
$assets = $this->getAssetsFast();
|
||||
|
||||
$this->sortAssets($assets['styles']);
|
||||
$this->sortAssets($assets['scripts']);
|
||||
$this->sortAssets($assets['html']);
|
||||
|
||||
return $assets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getFrameworks()
|
||||
{
|
||||
$assets = $this->getAssetsFast();
|
||||
|
||||
return array_keys($assets['frameworks']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $location
|
||||
* @return array
|
||||
*/
|
||||
public function getStyles($location = 'head')
|
||||
{
|
||||
return $this->getAssetsInLocation('styles', $location);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $location
|
||||
* @return array
|
||||
*/
|
||||
public function getScripts($location = 'head')
|
||||
{
|
||||
return $this->getAssetsInLocation('scripts', $location);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $location
|
||||
* @return array
|
||||
*/
|
||||
public function getHtml($location = 'bottom')
|
||||
{
|
||||
return $this->getAssetsInLocation('html', $location);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
$array = parent::toArray();
|
||||
|
||||
if ($this->frameworks) {
|
||||
$array['frameworks'] = $this->frameworks;
|
||||
}
|
||||
if ($this->styles) {
|
||||
$array['styles'] = $this->styles;
|
||||
}
|
||||
if ($this->scripts) {
|
||||
$array['scripts'] = $this->scripts;
|
||||
}
|
||||
if ($this->html) {
|
||||
$array['html'] = $this->html;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $serialized
|
||||
*/
|
||||
public function build(array $serialized)
|
||||
{
|
||||
parent::build($serialized);
|
||||
|
||||
$this->frameworks = isset($serialized['frameworks']) ? (array) $serialized['frameworks'] : [];
|
||||
$this->styles = isset($serialized['styles']) ? (array) $serialized['styles'] : [];
|
||||
$this->scripts = isset($serialized['scripts']) ? (array) $serialized['scripts'] : [];
|
||||
$this->html = isset($serialized['html']) ? (array) $serialized['html'] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $framework
|
||||
* @return $this
|
||||
*/
|
||||
public function addFramework($framework)
|
||||
{
|
||||
$this->frameworks[$framework] = 1;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array $element
|
||||
* @param int $priority
|
||||
* @param string $location
|
||||
* @return bool
|
||||
*
|
||||
* @example $block->addStyle('assets/js/my.js');
|
||||
* @example $block->addStyle(['href' => 'assets/js/my.js', 'media' => 'screen']);
|
||||
*/
|
||||
public function addStyle($element, $priority = 0, $location = 'head')
|
||||
{
|
||||
if (!is_array($element)) {
|
||||
$element = ['href' => (string) $element];
|
||||
}
|
||||
if (empty($element['href'])) {
|
||||
return false;
|
||||
}
|
||||
if (!isset($this->styles[$location])) {
|
||||
$this->styles[$location] = [];
|
||||
}
|
||||
|
||||
$id = !empty($element['id']) ? ['id' => (string) $element['id']] : [];
|
||||
$href = $element['href'];
|
||||
$type = !empty($element['type']) ? (string) $element['type'] : 'text/css';
|
||||
$media = !empty($element['media']) ? (string) $element['media'] : null;
|
||||
unset($element['tag'], $element['id'], $element['rel'], $element['content'], $element['href'], $element['type'], $element['media']);
|
||||
|
||||
$this->styles[$location][md5($href) . sha1($href)] = [
|
||||
':type' => 'file',
|
||||
':priority' => (int) $priority,
|
||||
'href' => $href,
|
||||
'type' => $type,
|
||||
'media' => $media,
|
||||
'element' => $element
|
||||
] + $id;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array $element
|
||||
* @param int $priority
|
||||
* @param string $location
|
||||
* @return bool
|
||||
*/
|
||||
public function addInlineStyle($element, $priority = 0, $location = 'head')
|
||||
{
|
||||
if (!is_array($element)) {
|
||||
$element = ['content' => (string) $element];
|
||||
}
|
||||
if (empty($element['content'])) {
|
||||
return false;
|
||||
}
|
||||
if (!isset($this->styles[$location])) {
|
||||
$this->styles[$location] = [];
|
||||
}
|
||||
|
||||
$content = (string) $element['content'];
|
||||
$type = !empty($element['type']) ? (string) $element['type'] : 'text/css';
|
||||
|
||||
$this->styles[$location][md5($content) . sha1($content)] = [
|
||||
':type' => 'inline',
|
||||
':priority' => (int) $priority,
|
||||
'content' => $content,
|
||||
'type' => $type
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array $element
|
||||
* @param int $priority
|
||||
* @param string $location
|
||||
* @return bool
|
||||
*/
|
||||
public function addScript($element, $priority = 0, $location = 'head')
|
||||
{
|
||||
if (!is_array($element)) {
|
||||
$element = ['src' => (string) $element];
|
||||
}
|
||||
if (empty($element['src'])) {
|
||||
return false;
|
||||
}
|
||||
if (!isset($this->scripts[$location])) {
|
||||
$this->scripts[$location] = [];
|
||||
}
|
||||
|
||||
$src = $element['src'];
|
||||
$type = !empty($element['type']) ? (string) $element['type'] : 'text/javascript';
|
||||
$defer = isset($element['defer']) ? true : false;
|
||||
$async = isset($element['async']) ? true : false;
|
||||
$handle = !empty($element['handle']) ? (string) $element['handle'] : '';
|
||||
|
||||
$this->scripts[$location][md5($src) . sha1($src)] = [
|
||||
':type' => 'file',
|
||||
':priority' => (int) $priority,
|
||||
'src' => $src,
|
||||
'type' => $type,
|
||||
'defer' => $defer,
|
||||
'async' => $async,
|
||||
'handle' => $handle
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array $element
|
||||
* @param int $priority
|
||||
* @param string $location
|
||||
* @return bool
|
||||
*/
|
||||
public function addInlineScript($element, $priority = 0, $location = 'head')
|
||||
{
|
||||
if (!is_array($element)) {
|
||||
$element = ['content' => (string) $element];
|
||||
}
|
||||
if (empty($element['content'])) {
|
||||
return false;
|
||||
}
|
||||
if (!isset($this->scripts[$location])) {
|
||||
$this->scripts[$location] = [];
|
||||
}
|
||||
|
||||
$content = (string) $element['content'];
|
||||
$type = !empty($element['type']) ? (string) $element['type'] : 'text/javascript';
|
||||
|
||||
$this->scripts[$location][md5($content) . sha1($content)] = [
|
||||
':type' => 'inline',
|
||||
':priority' => (int) $priority,
|
||||
'content' => $content,
|
||||
'type' => $type
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $html
|
||||
* @param int $priority
|
||||
* @param string $location
|
||||
* @return bool
|
||||
*/
|
||||
public function addHtml($html, $priority = 0, $location = 'bottom')
|
||||
{
|
||||
if (empty($html) || !is_string($html)) {
|
||||
return false;
|
||||
}
|
||||
if (!isset($this->html[$location])) {
|
||||
$this->html[$location] = [];
|
||||
}
|
||||
|
||||
$this->html[$location][md5($html) . sha1($html)] = [
|
||||
':priority' => (int) $priority,
|
||||
'html' => $html
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function getAssetsFast()
|
||||
{
|
||||
$assets = [
|
||||
'frameworks' => $this->frameworks,
|
||||
'styles' => $this->styles,
|
||||
'scripts' => $this->scripts,
|
||||
'html' => $this->html
|
||||
];
|
||||
|
||||
foreach ($this->blocks as $block) {
|
||||
if ($block instanceof HtmlBlock) {
|
||||
$blockAssets = $block->getAssetsFast();
|
||||
$assets['frameworks'] += $blockAssets['frameworks'];
|
||||
|
||||
foreach ($blockAssets['styles'] as $location => $styles) {
|
||||
if (!isset($assets['styles'][$location])) {
|
||||
$assets['styles'][$location] = $styles;
|
||||
} elseif ($styles) {
|
||||
$assets['styles'][$location] += $styles;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($blockAssets['scripts'] as $location => $scripts) {
|
||||
if (!isset($assets['scripts'][$location])) {
|
||||
$assets['scripts'][$location] = $scripts;
|
||||
} elseif ($scripts) {
|
||||
$assets['scripts'][$location] += $scripts;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($blockAssets['html'] as $location => $htmls) {
|
||||
if (!isset($assets['html'][$location])) {
|
||||
$assets['html'][$location] = $htmls;
|
||||
} elseif ($htmls) {
|
||||
$assets['html'][$location] += $htmls;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $assets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param string $location
|
||||
* @return array
|
||||
*/
|
||||
protected function getAssetsInLocation($type, $location)
|
||||
{
|
||||
$assets = $this->getAssetsFast();
|
||||
|
||||
if (empty($assets[$type][$location])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$styles = $assets[$type][$location];
|
||||
$this->sortAssetsInLocation($styles);
|
||||
|
||||
return $styles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $items
|
||||
*/
|
||||
protected function sortAssetsInLocation(array &$items)
|
||||
{
|
||||
$count = 0;
|
||||
foreach ($items as &$item) {
|
||||
$item[':order'] = ++$count;
|
||||
}
|
||||
uasort(
|
||||
$items,
|
||||
function ($a, $b) {
|
||||
return ($a[':priority'] == $b[':priority']) ? $a[':order'] - $b[':order'] : $a[':priority'] - $b[':priority'];
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $array
|
||||
*/
|
||||
protected function sortAssets(array &$array)
|
||||
{
|
||||
foreach ($array as $location => &$items) {
|
||||
$this->sortAssetsInLocation($items);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Grav\Framework\ContentBlock
|
||||
*
|
||||
* @copyright Copyright (C) 2014 - 2017 RocketTheme, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\ContentBlock;
|
||||
|
||||
/**
|
||||
* Interface HtmlBlockInterface
|
||||
* @package Grav\Framework\ContentBlock
|
||||
*/
|
||||
interface HtmlBlockInterface extends ContentBlockInterface
|
||||
{
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAssets();
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getFrameworks();
|
||||
|
||||
/**
|
||||
* @param string $location
|
||||
* @return array
|
||||
*/
|
||||
public function getStyles($location = 'head');
|
||||
|
||||
/**
|
||||
* @param string $location
|
||||
* @return array
|
||||
*/
|
||||
public function getScripts($location = 'head');
|
||||
|
||||
/**
|
||||
* @param string $location
|
||||
* @return array
|
||||
*/
|
||||
public function getHtml($location = 'bottom');
|
||||
|
||||
/**
|
||||
* @param string $framework
|
||||
* @return $this
|
||||
*/
|
||||
public function addFramework($framework);
|
||||
|
||||
/**
|
||||
* @param string|array $element
|
||||
* @param int $priority
|
||||
* @param string $location
|
||||
* @return bool
|
||||
*
|
||||
* @example $block->addStyle('assets/js/my.js');
|
||||
* @example $block->addStyle(['href' => 'assets/js/my.js', 'media' => 'screen']);
|
||||
*/
|
||||
public function addStyle($element, $priority = 0, $location = 'head');
|
||||
|
||||
/**
|
||||
* @param string|array $element
|
||||
* @param int $priority
|
||||
* @param string $location
|
||||
* @return bool
|
||||
*/
|
||||
public function addInlineStyle($element, $priority = 0, $location = 'head');
|
||||
|
||||
/**
|
||||
* @param string|array $element
|
||||
* @param int $priority
|
||||
* @param string $location
|
||||
* @return bool
|
||||
*/
|
||||
public function addScript($element, $priority = 0, $location = 'head');
|
||||
|
||||
|
||||
/**
|
||||
* @param string|array $element
|
||||
* @param int $priority
|
||||
* @param string $location
|
||||
* @return bool
|
||||
*/
|
||||
public function addInlineScript($element, $priority = 0, $location = 'head');
|
||||
|
||||
/**
|
||||
* @param string $html
|
||||
* @param int $priority
|
||||
* @param string $location
|
||||
* @return bool
|
||||
*/
|
||||
public function addHtml($html, $priority = 0, $location = 'bottom');
|
||||
}
|
||||
Reference in New Issue
Block a user