plugin = $plugin;
$this->bufferLevel = 0;
$this->assets = [];
$this->inlineJsCode = [];
$this->inlineCssCode = [];
$this->addAsset('AcfViewsMapsFrontAsset');
}
protected function addAsset(string $name): void
{
switch ($name) {
case 'AcfViewsMapsFrontAsset':
$this->assets[] = new AcfViewsMapsFrontAsset($this->plugin);
break;
}
}
protected function getWebComponentJs(CptData $cptData, string $jsCode): string
{
$tagName = $cptData->getTagName();
$isWebComponent = 'div' !== $tagName;
if (!$isWebComponent) {
return $jsCode;
}
// dashes to camelCase
$componentName = preg_replace_callback(
'/-([a-z0-9])/',
function ($matches) {
return strtoupper($matches[1]);
},
$tagName
);
return sprintf(
'class %s extends HTMLElement{connectedCallback(){"loading"===document.readyState?document.addEventListener("DOMContentLoaded",this.setup.bind(this)):this.setup()}setup(){%s}}customElements.define("%s", %s);',
esc_html($componentName),
$jsCode,
esc_html($tagName),
esc_html($componentName),
);
}
public function startBuffering(): void
{
ob_start();
$this->bufferLevel = ob_get_level();
}
public function printStylesStub(): void
{
echo '';
}
public function addAssets(CptData $cptData): void
{
$cssCode = $cptData->getCssCode();
$jsCode = $cptData->getJsCode();
if ($cssCode) {
$this->inlineCssCode[$cptData->getUniqueId()] = $cssCode;
}
if ($jsCode) {
$this->inlineJsCode[$cptData->getUniqueId()] = $this->getWebComponentJs($cptData, $jsCode);
}
foreach ($this->assets as $asset) {
$asset->maybeActivate($cptData);
}
}
public function printCustomAssets(): void
{
$allJsCode = '';
$allCssCode = '';
foreach ($this->inlineCssCode as $name => $cssCode) {
// no escaping, it's a CSS code, so e.g '.a > .b' shouldn't be escaped
$allCssCode .= sprintf("\n/*%s*/\n%s", $name, $cssCode);
}
foreach ($this->inlineJsCode as $name => $jsCode) {
$allJsCode .= sprintf("\n/*%s*/\n%s", $name, $jsCode);
}
if (!$allCssCode &&
!$allJsCode) {
// do not close the buffer, if it's not ours
// (then ours will be closed automatically with the end of script execution)
if (ob_get_level() === $this->bufferLevel) {
echo ob_get_clean();
}
return;
}
// close previous buffers. Some plugins may not close, if detect that ob_get_level() is another than was
// e.g. 'lightbox-photoswipe'
while (ob_get_level() > $this->bufferLevel) {
echo ob_get_clean();
}
$pageContent = ob_get_clean();
$cssTag = $allCssCode ?
sprintf("", $allCssCode) :
'';
$pageContent = str_replace('', $cssTag, $pageContent);
echo $pageContent;
if ($allJsCode) {
printf("", $allJsCode);
}
}
public function generateCode(CptData $cptData): array
{
$code = [];
foreach ($this->assets as $asset) {
$assetCode = $asset->generateCode($cptData);
if (!$assetCode['js'] &&
!$assetCode['css']) {
continue;
}
$code[$asset->getAutoDiscoverName()] = $assetCode;
}
return $code;
}
public function isWebComponentRequired(CptData $cptData): bool
{
foreach ($this->assets as $asset) {
if (!$asset->isWebComponentRequired($cptData)) {
continue;
}
return true;
}
return false;
}
public function getRowWrapperClass(FieldData $fieldData, string $type): string
{
$classes = [];
foreach ($this->assets as $asset) {
if (!($asset instanceof ViewFrontAsset) ||
!$asset->isTargetField($fieldData)) {
continue;
}
$class = $asset->getRowWrapperClass($fieldData, $type);
if (!$class) {
continue;
}
$classes[] = $class;
}
return implode(' ', $classes);
}
public function isLabelOutOfRow(FieldData $fieldData): bool
{
foreach ($this->assets as $asset) {
if (!($asset instanceof ViewFrontAsset) ||
!$asset->isTargetField($fieldData)) {
continue;
}
if ($asset->isLabelOutOfRow($fieldData)) {
return true;
}
}
return false;
}
public function getRowWrapperTag(FieldData $fieldData, string $rowType): string
{
foreach ($this->assets as $asset) {
if (!($asset instanceof ViewFrontAsset) ||
!$asset->isTargetField($fieldData)) {
continue;
}
$tag = $asset->getRowWrapperTag($fieldData, $rowType);
if (!$tag) {
continue;
}
return $tag;
}
return '';
}
public function getFieldWrapperTag(FieldData $fieldData, string $rowType): string
{
foreach ($this->assets as $asset) {
if (!($asset instanceof ViewFrontAsset) ||
!$asset->isTargetField($fieldData)) {
continue;
}
$tag = $asset->getFieldWrapperTag($fieldData, $rowType);
if (!$tag) {
continue;
}
return $tag;
}
switch ($fieldData->getFieldMeta()->getType()) {
case MenuFields::FIELD_ITEMS:
return 'ul';
}
return '';
}
public function getFieldWrapperAttrs(FieldData $fieldData, string $fieldId): array
{
$attrs = [];
foreach ($this->assets as $asset) {
if (!($asset instanceof ViewFrontAsset) ||
!$asset->isTargetField($fieldData)) {
continue;
}
$attrs = array_merge($attrs, $asset->getFieldWrapperAttrs($fieldData, $fieldId));
}
return $attrs;
}
public function getFieldOuters(ViewData $viewData, FieldData $fieldData, string $fieldId, string $rowType): array
{
$outers = [];
foreach ($this->assets as $asset) {
if (!($asset instanceof ViewFrontAsset) ||
!$asset->isTargetField($fieldData)) {
continue;
}
$assetOuters = $asset->getFieldOuters($viewData, $fieldData, $fieldId, $rowType);
if (!$assetOuters) {
continue;
}
$counter = 0;
foreach ($assetOuters as $assetOuter) {
$currentAttrs = $outers[$counter]['attrs'] ?? [];
$outers[$counter] = [
// override, as we need some consensus
'tag' => $assetOuter['tag'],
// merge, so all necessary are present
'attrs' => array_merge($currentAttrs, $assetOuter['attrs']),
];
$counter++;
}
}
return $outers;
}
public function getItemOuters(ViewData $viewData, FieldData $fieldData, string $fieldId, string $itemId): array
{
$outers = [];
foreach ($this->assets as $asset) {
if (!($asset instanceof ViewFrontAsset) ||
!$asset->isTargetField($fieldData)) {
continue;
}
$assetOuters = $asset->getItemOuters($viewData, $fieldData, $fieldId, $itemId);
if (!$assetOuters) {
continue;
}
$counter = 0;
foreach ($assetOuters as $assetOuter) {
$currentAttrs = $outers[$counter]['attrs'] ?? [];
$outers[$counter] = [
// override, as we need some consensus
'tag' => $assetOuter['tag'],
// merge, so all necessary are present
'attrs' => array_merge($currentAttrs, $assetOuter['attrs']),
];
$counter++;
}
}
return $outers;
}
public function getInnerAttributes(FieldData $fieldData, string $fieldId): string
{
$attributes = [];
foreach ($this->assets as $asset) {
if (!($asset instanceof ViewFrontAsset) ||
!$asset->isTargetField($fieldData)) {
continue;
}
$attribute = $asset->getInnerAttributes($fieldData, $fieldId);
if (!$attribute) {
continue;
}
$attributes[] = $attribute;
}
return implode(' ', $attributes);
}
public function getCardItemsWrapperClass(CardData $cardData): string
{
$classes = [];
foreach ($this->assets as $asset) {
if (!($asset instanceof CommonFrontAsset) ||
!$asset->isTargetCard($cardData)) {
continue;
}
$class = $asset->getCardItemsWrapperClass($cardData);
if (!$class) {
continue;
}
$classes[] = $class;
}
return implode(' ', $classes);
}
public function getCardItemOuters(CardData $cardData): array
{
$outers = [];
foreach ($this->assets as $asset) {
if (!($asset instanceof CommonFrontAsset) ||
!$asset->isTargetCard($cardData)) {
continue;
}
$assetOuters = $asset->getCardItemOuters($cardData);
if (!$assetOuters) {
continue;
}
$counter = 0;
foreach ($assetOuters as $assetOuter) {
$currentAttrs = $outers[$counter]['attrs'] ?? [];
$outers[$counter] = [
// override, as we need some consensus
'tag' => $assetOuter['tag'],
// merge, so all necessary are present
'attrs' => array_merge($currentAttrs, $assetOuter['attrs']),
];
$counter++;
}
}
return $outers;
}
public function getCardShortcodeAttrs(CardData $cardData): array
{
$attrs = [];
foreach ($this->assets as $asset) {
if (!($asset instanceof CommonFrontAsset) ||
!$asset->isTargetCard($cardData)) {
continue;
}
$attrs = array_merge($attrs, $asset->getCardShortcodeAttrs($cardData));
}
return $attrs;
}
public function enqueueAssets(): void
{
foreach ($this->assets as $asset) {
$asset->enqueueActive();
}
}
public function setHooks(bool $isAdmin): void
{
if ($isAdmin) {
return;
}
add_action('wp_footer', [$this, 'enqueueAssets']);
// printCustomAssets() contains ob_get_clean, so must be executed after all other scripts
add_action('wp_footer', [$this, 'printCustomAssets'], 9999);
add_action('wp_head', [$this, 'printStylesStub']);
// don't use 'get_header', as it doesn't work in blocks theme
add_action('template_redirect', [$this, 'startBuffering']);
}
}