Customize zend_form Captcha output?
Asked Answered
H

3

9

I'm using captcha in my zend_form.

$captcha_element = new Zend_Form_Element_Captcha(
    'captcha',
    array('label' => 'Write the chars to the field',
        'captcha' => array(
            'captcha' => 'Image',
            'wordLen' => 6,
            'timeout' => 300,
            'font' => DOC_ROOT . '/data/fonts/Vera.ttf',
            'imgDir' => $imagedir,
            'imgUrl' => $umageurl
        )
    )
);

This generates:

<dt id="captcha-input-label">
    <label for="captcha-input" class="required">Write the chars to the field</label>
</dt>

<dd id="captcha-element">
    <img width="200" height="50" alt="" src="http://sitename.com/captcha/09dd951939c6cdf7fa28f2b7d322ea95.png">
    <input type="hidden" name="captcha[id]" value="09dd951939c6cdf7fa28f2b7d322ea95" id="captcha-id">
    <input type="text" name="captcha[input]" id="captcha-input" value="">
</dd>

However. - I need following instead (captcha elements are wrapped into some tags individually):

<dt id="captcha-input-label">
    <label for="captcha-input" class="required">Write the chars to the field</label>
</dt>

<dd id="captcha-element">
    <div><span>
        <input type="text" name="captcha[input]" id="captcha-input" value="">
    </span></div>
    <div><span>
        <img width="200" height="50" alt="" src="http://sitename.com/captcha/09dd951939c6cdf7fa28f2b7d322ea95.png">
        <input type="hidden" name="captcha[id]" value="09dd951939c6cdf7fa28f2b7d322ea95" id="captcha-id">
    </span></div>
</dd>

I can't figure out how would I do this. Can I accomplish this by using some custom decorators? or woud that involve custom captcha ?

Haply answered 27/2, 2011 at 6:7 Comment(1)
This is not a trivial task. For example, you are changing the order of fields in captcha form element. This order is hard coded. Thus to just to change it you need to modify Zend_Form_Element_Captcha or create your own version of Zend_Form_Element_Captcha.Ensign
E
10

It was a bit tricky, but I prepared a custom Captcha element. I also needed to prepare custom Captcha decorator. In both cases I needed to override default render methods in both Zend_Form_Element_Captcha and Zend_Form_Decorator_Captcha. I also eliminated Zend_Form_Decorator_Captcha_Word since I incorporated its functionality directly into My_Form_Decorator_Captcha. There were two reasons for this. The first one is that order of form elements was changed, i.e. from default img, input hidden, input text into input text, img, input hidden. The second reason is that div and span tags needed to be added.

Hopefully, they will be helpful:

My_Form_Element_Captcha:

class My_Form_Element_Captcha extends Zend_Form_Element_Captcha {

    public function render(Zend_View_Interface $view = null)     {
        $captcha    = $this->getCaptcha();
        $captcha->setName($this->getFullyQualifiedName());

        $decorators = $this->getDecorators();

        // BELOW IS WHERE THE NEW DECORATOR IS USED

        $decorator = new My_Form_Decorator_Captcha(array('captcha' => $captcha));

        array_unshift($decorators, $decorator);

        $decorator  = $captcha->getDecorator();

        $this->setDecorators($decorators);


        $this->setValue($this->getCaptcha()->generate());

        return Zend_Form_Element::render($view);
    }
}

My_Form_Decorator_Captcha:

class My_Form_Decorator_Captcha extends Zend_Form_Decorator_Captcha {

     public function render($content) {
        $element = $this->getElement();
        if (!method_exists($element, 'getCaptcha')) {
            return $content;
        }

        $view = $element->getView();
        if (null === $view) {
            return $content;
        }


        $name = $element->getFullyQualifiedName();

        $hiddenName = $name . '[id]';
        $textName = $name . '[input]';

        $label = $element->getDecorator("Label");
        if ($label) {
            $label->setOption("id", $element->getId() . "-input");
        }

        $placement = $this->getPlacement();
        $separator = $this->getSeparator();

        $captcha = $element->getCaptcha();
        $markup = $captcha->render($view, $element);
        $hidden = $view->formHidden($hiddenName, $element->getValue(), $element->getAttribs());
        $text = $view->formText($textName, '', $element->getAttribs());


        // CHANGE THE ORDER OF ELEMENTS AND ADD THE div AND span TAGS.

        switch ($placement) {
            case 'PREPEND':
                $content = '<div><span>' . $text . '</div></span>' .
                        '<div><span>' . $markup . $hidden . '</div></span>' .
                        $separator . $content;
                break;
            case 'APPEND':
            default:
                $content = $content . $separator .
                        '<div><span>' . $text . '</div></span>' .
                        '<div><span>' . $markup . $hidden . '</div></span>';
        }

        return $content;
    }

}
Ensign answered 27/2, 2011 at 15:1 Comment(4)
omg Marcin - you are my hero. I was just tracing the same code trying to figure out how to accomplish this. Thanks a bunch.Haply
@Andre. I'm happy you like it.Ensign
Marcin i am using captcha without zend_form. i am using captcha code directly in controller , how i change view htmlRadcliff
Marcin , how we call on phtml file this custom renderRadcliff
E
3

I use simply

$captcha->setDescription('Enter code:')->setDecorators(array('captcha', array('ViewScript', array('viewScript' => 'auth/captcha.phtml')));

and inside viewscript:

<input id="captcha" type="text" name="captcha[input]" />

<input type="hidden" name="captcha[id]" value="<?php echo $this->element->getValue() ?>" >
<div  id="captcha-element">
    <?php echo $this->element->getCaptcha()->render(); ?>
</div>
Ezzo answered 16/8, 2012 at 18:50 Comment(0)
I
1

answer; Captcha, submit and other text elements for bootstrap 3 syntax

good luck

<?php
/**
 * User: semihs
 * Date: 05.08.2013
 * Time: 23:46
 */

class Form_Decorator_Horizontal extends Zend_Form_Decorator_Abstract {

    public function buildLabel() {
        $element = $this->getElement();
        $label   = $element->getLabel();
        if ($translator = $element->getTranslator()) {
            $label = $translator->translate($label);
        }

        if ($element->getType() == 'Zend_Form_Element_Submit') {
            return "<label for='{$element->getName()}' class='col-lg-4 control-label'></label>";
        } else {
            return "<label for='{$element->getName()}' class='col-lg-4 control-label'>{$label}</label>";
        }
    }

    public function buildInput() {
        $element = $this->getElement();
        $helper  = $element->helper;

        $element->setAttrib('class', $element->getAttrib('class') . " form-control");

        if ($element->getType() == 'Zend_Form_Element_Submit') {
            return "<div class='col-lg-8'>" . $element->getView()->$helper(
                $element->getName(),
                $element->getValue(),
                $element->getAttribs(),
                $element->options
            ) . "</div>";
        } else {
            return "<div class='col-lg-8'>" . $element->getView()->$helper(
                $element->getName(),
                $element->getValue(),
                $element->getAttribs(),
                $element->options
            ) . "</div>";
        }
    }

    public function buildErrors() {
        $element  = $this->getElement();
        $messages = $element->getMessages();
        if (empty($messages)) {
            return '';
        }

        return '<div class="errors">' . $element->getView()->formErrors($messages) . '</div>';
    }

    public function buildDescription() {
        $element = $this->getElement();
        $desc    = $element->getDescription();
        if (empty($desc)) {
            return '';
        }

        return '<div class="description">' . $desc . '</div>';
    }

    public function render($content) {
        $element = $this->getElement();

        if (!$element instanceof Zend_Form_Element) {
            return $content;
        }
        if (null === $element->getView()) {
            return $content;
        }

        $separator = $this->getSeparator();
        $placement = $this->getPlacement();
        $label     = $this->buildLabel();
        $input     = $this->buildInput();
        $errors    = $this->buildErrors();
        $desc      = $this->buildDescription();

        if ($element->getType() == 'Zend_Form_Element_Captcha') {
            $view = $element->getView();
            if (null === $view) {
                return $content;
            }

            $name = $element->getFullyQualifiedName();

            $hiddenName = $name . '[id]';
            $textName   = $name . '[input]';
            $captcha    = $element->getCaptcha();
            $markup     = $captcha->render($view, $element);
            $hidden     = $view->formHidden($hiddenName, $element->getValue(), $element->getAttribs());
            $text       = $view->formText($textName, '', $element->getAttribs());

            $output = '<div class="form-group">'
                . $label
                . "<div class='col-lg-8'>" . $markup . "</div>"
                . "</div>"
                . "<div class='form-group'>"
                . "<label class='col-lg-4'></label>"
                . "<div class='col-lg-8'>" . $text . "</div>"
                . $hidden
                . $errors
                . $desc
                . "</div>";
        } else {
            $output = '<div class="form-group">'
                . $label
                . $input
                . $errors
                . $desc
                . '</div>';
        }

        switch ($placement) {
            case (self::PREPEND):
                return $output . $separator . $content;
            case (self::APPEND):
            default:
                return $separator . $output;
        }
    }
}
Interfluve answered 5/8, 2013 at 22:54 Comment(1)
You should probably add an explanation.Peters

© 2022 - 2024 — McMap. All rights reserved.