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