1<?php 2/** 3 * Copyright (c) 2020. ComboStrap, Inc. and its affiliates. All Rights Reserved. 4 * 5 * This source code is licensed under the GPL license found in the 6 * COPYING file in the root directory of this source tree. 7 * 8 * @license GPL 3 (https://www.gnu.org/licenses/gpl-3.0.en.html) 9 * @author ComboStrap <support@combostrap.com> 10 * 11 */ 12 13use ComboStrap\ConditionalValue; 14use ComboStrap\PluginUtility; 15use ComboStrap\TagAttributes; 16 17 18require_once(__DIR__ . '/../class/PluginUtility.php'); 19 20/** 21 * The {@link https://combostrap.com/column column} of a {@link https://combostrap.com/grid grid} 22 * 23 * 24 * Note: The name of the class must follow this pattern ie syntax_plugin_PluginName_ComponentName 25 */ 26class syntax_plugin_combo_cell extends DokuWiki_Syntax_Plugin 27{ 28 29 const TAG = "cell"; 30 31 const WIDTH_ATTRIBUTE = TagAttributes::WIDTH_KEY; 32 const VERTICAL_ATTRIBUTE = "vertical"; 33 34 static function getTags() 35 { 36 return [self::TAG, "col", "column"]; 37 } 38 39 /** 40 * Syntax Type. 41 * 42 * Needs to return one of the mode types defined in $PARSER_MODES in parser.php 43 * @see DokuWiki_Syntax_Plugin::getType() 44 */ 45 function getType() 46 { 47 return 'container'; 48 } 49 50 /** 51 * @return array 52 * Allow which kind of plugin inside 53 * All 54 */ 55 public function getAllowedTypes() 56 { 57 return array('container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs'); 58 } 59 60 public function accepts($mode) 61 { 62 63 /** 64 * header mode is disable to take over 65 * and replace it with {@link syntax_plugin_combo_heading} 66 */ 67 if ($mode == "header") { 68 return false; 69 } 70 71 72 return syntax_plugin_combo_preformatted::disablePreformatted($mode); 73 74 } 75 76 /** 77 * How Dokuwiki will add P element 78 * 79 * * 'normal' - The plugin can be used inside paragraphs 80 * * 'block' - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs 81 * * 'stack' - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs 82 * 83 * @see DokuWiki_Syntax_Plugin::getPType() 84 */ 85 function getPType() 86 { 87 return 'stack'; 88 } 89 90 /** 91 * @see Doku_Parser_Mode::getSort() 92 * 93 * the mode with the lowest sort number will win out 94 * the container (parent) must then have a lower number than the child 95 */ 96 function getSort() 97 { 98 return 100; 99 } 100 101 /** 102 * Create a pattern that will called this plugin 103 * 104 * @param string $mode 105 * @see Doku_Parser_Mode::connectTo() 106 */ 107 function connectTo($mode) 108 { 109 110 // A cell can be anywhere 111 foreach (self::getTags() as $tag) { 112 $pattern = PluginUtility::getContainerTagPattern($tag); 113 $this->Lexer->addEntryPattern($pattern, $mode, PluginUtility::getModeForComponent($this->getPluginComponent())); 114 } 115 116 117 } 118 119 public function postConnect() 120 { 121 122 foreach (self::getTags() as $tag) { 123 $this->Lexer->addExitPattern('</' . $tag . '>', PluginUtility::getModeForComponent($this->getPluginComponent())); 124 } 125 126 } 127 128 /** 129 * 130 * The handle function goal is to parse the matched syntax through the pattern function 131 * and to return the result for use in the renderer 132 * This result is always cached until the page is modified. 133 * @param string $match 134 * @param int $state 135 * @param int $pos 136 * @param Doku_Handler $handler 137 * @return array|bool 138 * @see DokuWiki_Syntax_Plugin::handle() 139 * 140 */ 141 function handle($match, $state, $pos, Doku_Handler $handler) 142 { 143 144 switch ($state) { 145 146 case DOKU_LEXER_ENTER: 147 148 $attributes = TagAttributes::createFromTagMatch($match)->toCallStackArray(); 149 return array( 150 PluginUtility::STATE => $state, 151 PluginUtility::ATTRIBUTES => $attributes); 152 153 case DOKU_LEXER_UNMATCHED: 154 return PluginUtility::handleAndReturnUnmatchedData(self::TAG, $match, $handler); 155 156 case DOKU_LEXER_EXIT : 157 158 return array( 159 PluginUtility::STATE => $state 160 ); 161 162 163 } 164 165 return array(); 166 167 } 168 169 /** 170 * Render the output 171 * @param string $format 172 * @param Doku_Renderer $renderer 173 * @param array $data - what the function handle() return'ed 174 * @return boolean - rendered correctly? (however, returned value is not used at the moment) 175 * @see DokuWiki_Syntax_Plugin::render() 176 * 177 * 178 */ 179 function render($format, Doku_Renderer $renderer, $data) 180 { 181 182 if ($format == 'xhtml') { 183 184 /** @var Doku_Renderer_xhtml $renderer */ 185 $state = $data[PluginUtility::STATE]; 186 switch ($state) { 187 188 case DOKU_LEXER_ENTER : 189 190 PluginUtility::getSnippetManager()->attachCssSnippetForBar(self::TAG); 191 $callStackArray = $data[PluginUtility::ATTRIBUTES]; 192 $attributes = TagAttributes::createFromCallStackArray($callStackArray, self::TAG); 193 $attributes->addClassName("col"); 194 if ($attributes->hasComponentAttribute(self::VERTICAL_ATTRIBUTE)) { 195 $value = $attributes->getValue(self::VERTICAL_ATTRIBUTE); 196 if ($value == "center") { 197 //$attributes->addClassName("d-inline-flex"); 198 $attributes->addClassName("align-self-center"); 199 } 200 } 201 if ($attributes->hasComponentAttribute(syntax_plugin_combo_cell::WIDTH_ATTRIBUTE)) { 202 $sizeValues = $attributes->getValuesAndRemove(syntax_plugin_combo_cell::WIDTH_ATTRIBUTE); 203 foreach ($sizeValues as $sizeValue) { 204 $conditionalValue = ConditionalValue::createFrom($sizeValue); 205 if ($conditionalValue->getBreakpoint() == "xs") { 206 $attributes->addClassName("col-" . $conditionalValue->getValue()); 207 } else { 208 if ($conditionalValue->getBreakpoint() != null) { 209 $attributes->addClassName("col-$sizeValue"); 210 } else { 211 /** 212 * No breakpoint given 213 * If this is a number between 1 and 12, 214 * we take the assumption that this is a ratio 215 * otherwise, this a width in CSS length 216 */ 217 if ($sizeValue >= 1 && $sizeValue <= syntax_plugin_combo_row::GRID_TOTAL_COLUMNS) { 218 $attributes->addClassName("col-$sizeValue"); 219 } else { 220 $attributes->addComponentAttributeValue(TagAttributes::WIDTH_KEY, $sizeValue); 221 } 222 } 223 } 224 } 225 } 226 $renderer->doc .= $attributes->toHtmlEnterTag("div") . DOKU_LF; 227 break; 228 229 case DOKU_LEXER_UNMATCHED : 230 231 $renderer->doc .= PluginUtility::renderUnmatched($data); 232 break; 233 234 case DOKU_LEXER_EXIT : 235 236 $renderer->doc .= '</div>' . DOKU_LF; 237 break; 238 } 239 return true; 240 } 241 return false; 242 } 243 244 245} 246