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