xref: /plugin/combo/ComboStrap/IdentityFormsHelper.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
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