1<?php 2 3namespace ComboStrap; 4 5use Doku_Form; 6use dokuwiki\Form\Form; 7use dokuwiki\Form\InputElement; 8 9class IdentityFormsHelper 10{ 11 12 const CANONICAL = "identity-forms-helper"; 13 14 public static function toBoostrapInputElements(Form $form, string $formName) 15 { 16 for ($i = 0; $i < $form->elementCount(); $i++) { 17 $inputElement = $form->getElementAt($i); 18 if ($inputElement instanceof InputElement) { 19 $i = self::toBootStrapInputElementAndGetNewLoopingPosition($form, $i, $formName); 20 } 21 } 22 } 23 24 /** 25 * Tansfrom the Dokuwiki {@link InputElement} into a Boostrap layout 26 * @param Form $form - the form 27 * @param int $elementPosition - the position of the element (that's how works {@link Form} 28 * @param string $formName - the form name to create unique id (as the profile page has 2 forms) 29 * @return int - the new position that should be used in a loop (the remove, add action reset the whole array indexes) 30 */ 31 public static function toBootStrapInputElementAndGetNewLoopingPosition(Form $form, int $elementPosition, string $formName): int 32 { 33 $inputElement = $form->getElementAt($elementPosition); 34 if (!($inputElement instanceof InputElement)) { 35 LogUtility::internalError("The element should be an input element"); 36 return $elementPosition; 37 } 38 $inputType = $inputElement->getType(); 39 $inputName = $inputElement->attr("name"); 40 $labelObject = $inputElement->getLabel(); 41 $label = ""; 42 if ($labelObject !== null) { 43 $label = $labelObject->val(); 44 } 45 $inputId = $inputElement->attr("id"); 46 if (empty($inputId)) { 47 $inputId = "user__$formName-input-$elementPosition"; 48 $inputElement->id($inputId); 49 } 50 $placeholder = $inputElement->attr("placeholder"); 51 if (empty($placeholder) && !empty($label)) { 52 $inputElement->attr("placeholder", $label); 53 } 54 $newInputField = new InputElement($inputType, $inputName); 55 foreach ($inputElement->attrs() as $keyAttr => $valueAttr) { 56 $newInputField->attr($keyAttr, $valueAttr); 57 } 58 $newInputField->addClass("form-control"); 59 $form->replaceElement($newInputField, $elementPosition); 60 $form->addHTML('<div class="form-control-row">', $elementPosition); 61 $form->addHTML("<label for=\"$inputId\" class=\"form-label\">$label</label>", $elementPosition + 1); 62 $form->addHTML('</div>', $elementPosition + 3); 63 return $elementPosition + 3; 64 65 } 66 67 /** 68 * @param Doku_Form|Form $form 69 * @param string $classPrefix 70 * @param bool $includeLogo 71 * @return string 72 */ 73 public static function getHeaderHTML($form, string $classPrefix, bool $includeLogo = true): string 74 { 75 $class = get_class($form); 76 switch ($class) { 77 case Doku_Form::class: 78 /** 79 * Old one 80 * @var Doku_Form $form 81 */ 82 $legend = $form->_content[0]["_legend"]; 83 if (!isset($legend)) { 84 return ""; 85 } 86 87 $title = $legend; 88 break; 89 case Form::class; 90 /** 91 * New One 92 * @var Form $form 93 */ 94 $pos = $form->findPositionByType("fieldsetopen"); 95 if ($pos === false) { 96 return ""; 97 } 98 99 $title = $form->getElementAt($pos)->val(); 100 break; 101 default: 102 LogUtility::msg("Internal Error: Unknown form class " . $class); 103 return ""; 104 } 105 106 /** 107 * Logo 108 */ 109 $logoHtmlImgTag = ""; 110 if ( 111 $includeLogo === true 112 ) { 113 try { 114 $logoPath = self::getLogoPath(); 115 } catch (ExceptionNotFound $e) { 116 $logoPath = WikiPath::createComboResource(":images:home.svg"); 117 } 118 $logoHtmlImgTag = self::getLogoHtml($logoPath); 119 } 120 /** 121 * Don't use `header` in place of 122 * div because this is a HTML5 tag 123 * 124 * On php 5.6, the php test library method {@link \phpQueryObject::htmlOuter()} 125 * add the below meta tag 126 * <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> 127 * 128 */ 129 return <<<EOF 130<div class="$classPrefix-header"> 131 $logoHtmlImgTag 132 <h1>$title</h1> 133</div> 134EOF; 135 } 136 137 public static function addPrimaryColorCssRuleIfSet(?string $content): ?string 138 { 139 if ($content === null) { 140 return null; 141 } 142 $primaryColor = Site::getPrimaryColor(); 143 if ($primaryColor !== null) { 144 $identityClass = Identity::FORM_IDENTITY_CLASS; 145 $cssFormControl = BrandingColors::getCssFormControlFocusColor($primaryColor); 146 $content .= <<<EOF 147.$identityClass button[type="submit"]{ 148 background-color: {$primaryColor->toCssValue()}; 149 border-color: {$primaryColor->toCssValue()}; 150} 151$cssFormControl 152EOF; 153 } 154 return $content; 155 } 156 157 public static function getHtmlStyleTag(string $componentId): string 158 { 159 $loginCss = Snippet::createCssSnippetFromComponentId($componentId); 160 try { 161 $content = $loginCss->getInternalInlineAndFileContent(); 162 } catch (ExceptionNotFound $e) { 163 LogUtility::internalError("The style content should be not null", Identity::CANONICAL); 164 $content = ""; 165 } 166 $content = IdentityFormsHelper::addPrimaryColorCssRuleIfSet($content); 167 $class = $loginCss->getClass(); 168 return <<<EOF 169<style class="$class"> 170$content 171</style> 172EOF; 173 174 } 175 176 public static function addIdentityClass(&$class, string $formClass) 177 { 178 179 $formClass = Identity::FORM_IDENTITY_CLASS . " " . $formClass; 180 if (isset($class)) { 181 $class .= " " . $formClass; 182 } else { 183 $class = $formClass; 184 } 185 186 } 187 188 public static function deleteFieldSetAndBrFromForm(Form $form) 189 { 190 foreach (Identity::FIELD_SET_TO_DELETE as $type) { 191 $field = $form->findPositionByType($type); 192 if ($field !== false) { 193 $form->removeElement($field); 194 } 195 } 196 197 for ($i = 0; $i < $form->elementCount(); $i++) { 198 $fieldBr = $form->getElementAt($i); 199 if (trim($fieldBr->val()) === "<br>") { 200 $form->removeElement($i); 201 // removing the element, rearrange the array and shift the array index of minus 1 202 // to delete two br one after the other, we need to readjust the counter 203 $i--; 204 } 205 } 206 } 207 208 public static function toBootStrapSubmitButton(Form $form) 209 { 210 $submitButtonPosition = $form->findPositionByAttribute("type", "submit"); 211 if ($submitButtonPosition === false) { 212 LogUtility::msg("Internal error: No submit button found"); 213 return; 214 } 215 $form->getElementAt($submitButtonPosition) 216 ->addClass("btn") 217 ->addClass("btn-primary"); 218 } 219 220 public static function toBootstrapResetButton(Form $form) 221 { 222 $resetButtonPosition = $form->findPositionByAttribute("type", "reset"); 223 if ($resetButtonPosition === false) { 224 LogUtility::msg("Internal error: No submit button found"); 225 return; 226 } 227 $form->getElementAt($resetButtonPosition) 228 ->addClass("btn") 229 ->addClass("btn-secondary"); 230 } 231 232 /** 233 */ 234 public static function getLogoHtml(WikiPath $logoImagePath): string 235 { 236 237 $tagAttributes = TagAttributes::createEmpty("identity") 238 ->addClassName("logo"); 239 240 try { 241 $imageFetcher = IFetcherLocalImage::createImageFetchFromPath($logoImagePath) 242 ->setRequestedHeight(72) 243 ->setRequestedWidth(72); 244 245 if ($imageFetcher instanceof FetcherSvg) { 246 $imageFetcher->setRequestedType(FetcherSvg::ICON_TYPE); 247 $primaryColor = Site::getPrimaryColor(); 248 if ($primaryColor !== null) { 249 $imageFetcher->setRequestedColor($primaryColor); 250 } 251 } 252 $brand = Brand::create(Brand::CURRENT_BRAND); 253 254 $mediaMarkup = MediaMarkup::createFromFetcher($imageFetcher) 255 ->setLazyLoad(false) 256 ->setLinking(MediaMarkup::LINKING_NOLINK_VALUE) 257 ->buildFromTagAttributes($tagAttributes) 258 ->toHtml(); 259 return <<<EOF 260<a href="{$brand->getBrandUrl()}" title="{$brand->getTitle()}">$mediaMarkup</a> 261EOF; 262 } catch (\Exception $e) { 263 LogUtility::error("Error while creating the logo html", self::CANONICAL, $e); 264 return ""; 265 } 266 267 } 268 269 /** 270 * @throws ExceptionNotFound 271 */ 272 public static function getLogoPath(): WikiPath 273 { 274 $logoImagesPath = Site::getLogoImagesAsPath(); 275 foreach ($logoImagesPath as $logoImagePath) { 276 277 if (!Identity::isReader($logoImagePath->getWikiId())) { 278 continue; 279 } 280 return $logoImagePath; 281 282 } 283 throw new ExceptionNotFound("No logo image could be found"); 284 } 285} 286